KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_git_switch.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/gpl-3.0.html
19 * or you may search the http://www.gnu.org website for the version 3 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24
25#include "dialog_git_switch.h"
26
27#include <wx/button.h>
28#include <wx/checkbox.h>
29#include <wx/listctrl.h>
30#include <wx/event.h>
31#include <wx/sizer.h>
32#include <wx/stattext.h>
33#include <wx/textctrl.h>
34
35#include <git2.h>
36
37
38DIALOG_GIT_SWITCH::DIALOG_GIT_SWITCH( wxWindow* aParent, git_repository* aRepository ) :
39 DIALOG_SHIM( aParent, wxID_ANY, _( "Git Branch Switch" ), wxDefaultPosition, wxDefaultSize,
40 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
41 m_timer( this ), m_repository( aRepository )
42{
43 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
44
45 // Add explanation text
46 wxStaticText* explanationText =
47 new wxStaticText( this, wxID_ANY, _( "Select or enter a branch name:" ) );
48 sizer->Add( explanationText, 0, wxALL, 10 );
49
50 // Add branch list with three columns
51 m_branchList = new wxListView( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
52 wxLC_REPORT | wxLC_SINGLE_SEL );
53 m_branchList->InsertColumn( 0, _( "Branch" ) );
54 m_branchList->InsertColumn( 1, _( "Last Commit" ) );
55 m_branchList->InsertColumn( 2, _( "Last Updated" ) );
56 sizer->Add( m_branchList, 1, wxALL | wxEXPAND, 10 );
57
58 // Add branch name text box
59 m_branchNameText = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
60 wxDefaultSize, wxTE_PROCESS_ENTER );
61 sizer->Add( m_branchNameText, 0, wxALL | wxEXPAND, 10 );
62
63 // Add buttons
64 wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer();
65 m_switchButton = new wxButton( this, wxID_OK, _( "Switch" ) );
66 buttonSizer->AddButton( m_switchButton );
67 m_switchButton->Disable();
68 wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
69 buttonSizer->AddButton( cancelButton );
70 buttonSizer->Realize();
71 sizer->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 10 );
72
73 // Bind events
74 Bind( wxEVT_LIST_ITEM_SELECTED, &DIALOG_GIT_SWITCH::OnBranchListSelection, this, m_branchList->GetId() );
75 Bind( wxEVT_LIST_ITEM_ACTIVATED, &DIALOG_GIT_SWITCH::OnBranchListDClick, this, m_branchList->GetId() );
76 Bind( wxEVT_BUTTON, &DIALOG_GIT_SWITCH::OnSwitchButton, this, m_switchButton->GetId() );
77 Bind( wxEVT_BUTTON, &DIALOG_GIT_SWITCH::OnCancelButton, this, cancelButton->GetId() );
78 Bind( wxEVT_TEXT, &DIALOG_GIT_SWITCH::OnTextChanged, this, m_branchNameText->GetId() );
79 Bind( wxEVT_TIMER, &DIALOG_GIT_SWITCH::OnTimer, this, m_timer.GetId() );
80
81 // Populate branch list
83
84 // Set sizer for the dialog
85 SetSizerAndFit( sizer );
86
88
89 m_existingBranch = false;
90}
91
93{
94 StopTimer();
95 Unbind( wxEVT_TIMER, &DIALOG_GIT_SWITCH::OnTimer, this, m_timer.GetId() );
96}
97
99{
100 m_branchList->DeleteAllItems();
101
102 // Get the branches
103 GetBranches();
104
105 // Populate the list
106 for( auto& [ name, data ] : m_branches )
107 {
108 wxDateTime lastUpdated( data.lastUpdated );
109 wxString lastUpdatedString = lastUpdated.Format();
110
111 long itemIndex = m_branchList->InsertItem( m_branchList->GetItemCount(), name );
112 m_branchList->SetItem( itemIndex, 1, data.commitString );
113 m_branchList->SetItem( itemIndex, 2, lastUpdatedString );
114 }
115
116 m_branchList->SetColumnWidth( 0, wxLIST_AUTOSIZE );
117 m_branchList->SetColumnWidth( 1, wxLIST_AUTOSIZE );
118 m_branchList->SetColumnWidth( 2, wxLIST_AUTOSIZE );
119
120}
121
122
123void DIALOG_GIT_SWITCH::OnBranchListDClick( wxListEvent& aEvent )
124{
125 int selection = aEvent.GetIndex();
126
127 if( selection != wxNOT_FOUND )
128 {
129 wxString branchName = m_branchList->GetItemText( selection );
130 m_branchNameText->SetValue( branchName );
131
132 if( branchName != m_currentBranch )
133 EndModal( wxID_OK );
134 }
135}
136
137
139{
140 int selection = aEvent.GetIndex();
141
142 if( selection != wxNOT_FOUND )
143 {
144 wxString branchName = m_branchList->GetItemText( selection );
145 m_branchNameText->SetValue( branchName );
146 m_switchButton->SetLabel( _( "Switch" ) );
147 m_switchButton->Enable( branchName != m_currentBranch );
148 }
149 else
150 {
151 // Deselect all elements in the list
152 for( int ii = 0; ii < m_branchList->GetItemCount(); ++ii )
153 m_branchList->SetItemState( ii, 0, 0 );
154 }
155}
156
157void DIALOG_GIT_SWITCH::OnSwitchButton(wxCommandEvent& aEvent)
158{
159 wxString branchName = m_branchNameText->GetValue();
160
161 // Check if the branch name exists
162 bool branchExists = m_branches.count(branchName);
163
164 if (branchExists)
165 {
166 EndModal(wxID_OK); // Return Switch code
167 }
168 else
169 {
170 EndModal(wxID_ADD); // Return Add code
171 }
172}
173
174
175void DIALOG_GIT_SWITCH::OnCancelButton(wxCommandEvent& aEvent)
176{
177 EndModal(wxID_CANCEL); // Return Cancel code
178}
179
180
182{
183 return m_branchNameText->GetValue();
184}
185
186
188{
189 m_timer.Start( 500, true );
190}
191
192
194{
195 m_timer.Stop();
196}
197
198
199void DIALOG_GIT_SWITCH::OnTimer( wxTimerEvent& aEvt )
200{
201 wxString branchName = m_branchNameText->GetValue();
202
203 if( branchName == m_lastEnteredText )
204 return;
205
206 m_lastEnteredText = branchName;
207
208 // Check if the branch name exists
209 bool branchExists = m_branches.count( branchName );
210
211 if( branchExists )
212 {
213 m_switchButton->SetLabel( _( "Switch" ) );
214 m_switchButton->Enable( branchName != m_currentBranch );
215 }
216 else
217 {
218 m_switchButton->SetLabel( _( "Add" ) );
219 m_switchButton->Enable();
220 }
221}
222
223
224void DIALOG_GIT_SWITCH::OnTextChanged( wxCommandEvent& aEvt )
225{
226 StartTimer();
227}
228
229
231{
232 // Clear the branch list
233 m_branches.clear();
234
235 git_branch_iterator* branchIterator = nullptr;
236 git_branch_t branchType;
237
238 // Get Current Branch
239 git_reference* currentBranchReference = nullptr;
240 git_repository_head( &currentBranchReference, m_repository );
241
242 // Get the current branch name
243 if( currentBranchReference )
244 {
245 m_currentBranch = git_reference_shorthand( currentBranchReference );
246 git_reference_free( currentBranchReference );
247 }
248
249 // Initialize branch iterator
250 git_branch_iterator_new( &branchIterator, m_repository, GIT_BRANCH_ALL );
251
252 // Iterate over local branches
253 git_reference* branchReference = nullptr;
254 while( git_branch_next( &branchReference, &branchType, branchIterator ) == 0 )
255 {
256 // Get the branch OID
257 const git_oid* branchOid = git_reference_target( branchReference );
258
259 // Skip this branch if it doesn't have an OID
260 if( !branchOid )
261 {
262 git_reference_free( branchReference );
263 continue;
264 }
265
266 git_commit* commit = nullptr;
267
268 if( git_commit_lookup( &commit, m_repository, branchOid ) )
269 {
270 // Skip this branch if it doesn't have a commit
271 git_reference_free( branchReference );
272 continue;
273 }
274
275 // Retrieve commit details
276 BranchData branchData;
277 branchData.commitString = git_commit_message( commit );
278 branchData.lastUpdated = static_cast<time_t>( git_commit_time( commit ) );
279 branchData.isRemote = branchType == GIT_BRANCH_REMOTE;
280
281 m_branches[git_reference_shorthand( branchReference )] = branchData;
282
283 git_commit_free( commit );
284 git_reference_free( branchReference );
285 }
286
287 git_branch_iterator_free( branchIterator );
288}
const char * name
Definition: DXF_plotter.cpp:57
DIALOG_GIT_SWITCH(wxWindow *aParent, git_repository *aRepository)
wxListView * m_branchList
git_repository * m_repository
wxString GetBranchName() const
void OnTextChanged(wxCommandEvent &event)
wxButton * m_switchButton
std::map< wxString, BranchData > m_branches
void OnCancelButton(wxCommandEvent &event)
wxTextCtrl * m_branchNameText
void OnBranchListSelection(wxListEvent &event)
void OnBranchListDClick(wxListEvent &event)
void OnTimer(wxTimerEvent &event)
void OnSwitchButton(wxCommandEvent &event)
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:84
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
#define _(s)
wxString commitString
time_t lastUpdated