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/timer.h>
33#include <wx/stattext.h>
34#include <wx/textctrl.h>
35
36#include <git2.h>
37
38
39DIALOG_GIT_SWITCH::DIALOG_GIT_SWITCH( wxWindow* aParent, git_repository* aRepository ) :
40 DIALOG_SHIM( aParent, wxID_ANY, _( "Git Branch Switch" ), wxDefaultPosition, wxDefaultSize,
41 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
42 m_timer( this ), m_repository( aRepository )
43{
44 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
45
46 // Add explanation text
47 wxStaticText* explanationText =
48 new wxStaticText( this, wxID_ANY, _( "Select or enter a branch name:" ) );
49 sizer->Add( explanationText, 0, wxALL, 10 );
50
51 // Add branch list with three columns
52 m_branchList = new wxListView( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
53 wxLC_REPORT | wxLC_SINGLE_SEL );
54 m_branchList->InsertColumn( 0, _( "Branch" ) );
55 m_branchList->InsertColumn( 1, _( "Last Commit" ) );
56 m_branchList->InsertColumn( 2, _( "Last Updated" ) );
57 sizer->Add( m_branchList, 1, wxALL | wxEXPAND, 10 );
58
59 // Add branch name text box
60 m_branchNameText = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
61 wxDefaultSize, wxTE_PROCESS_ENTER );
62 sizer->Add( m_branchNameText, 0, wxALL | wxEXPAND, 10 );
63
64 // Add buttons
65 wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer();
66 m_switchButton = new wxButton( this, wxID_OK, _( "Switch" ) );
67 buttonSizer->AddButton( m_switchButton );
68 m_switchButton->Disable();
69 wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
70 buttonSizer->AddButton( cancelButton );
71 buttonSizer->Realize();
72 sizer->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 10 );
73
74 // Bind events
75 Bind( wxEVT_LIST_ITEM_SELECTED, &DIALOG_GIT_SWITCH::OnBranchListSelection, this, m_branchList->GetId() );
76 Bind( wxEVT_LIST_ITEM_ACTIVATED, &DIALOG_GIT_SWITCH::OnBranchListDClick, this, m_branchList->GetId() );
77 Bind( wxEVT_BUTTON, &DIALOG_GIT_SWITCH::OnSwitchButton, this, m_switchButton->GetId() );
78 Bind( wxEVT_BUTTON, &DIALOG_GIT_SWITCH::OnCancelButton, this, cancelButton->GetId() );
79 Bind( wxEVT_TEXT, &DIALOG_GIT_SWITCH::OnTextChanged, this, m_branchNameText->GetId() );
80 Bind( wxEVT_TIMER, &DIALOG_GIT_SWITCH::OnTimer, this, m_timer.GetId() );
81
82 // Populate branch list
84
85 // Set sizer for the dialog
86 SetSizerAndFit( sizer );
87
89
90 m_existingBranch = false;
91}
92
94{
95 StopTimer();
96 Unbind( wxEVT_TIMER, &DIALOG_GIT_SWITCH::OnTimer, this, m_timer.GetId() );
97}
98
100{
101 m_branchList->DeleteAllItems();
102
103 // Get the branches
104 GetBranches();
105
106 // Populate the list
107 for( auto& [ name, data ] : m_branches )
108 {
109 wxDateTime lastUpdated( data.lastUpdated );
110 wxString lastUpdatedString = lastUpdated.Format();
111
112 long itemIndex = m_branchList->InsertItem( m_branchList->GetItemCount(), name );
113 m_branchList->SetItem( itemIndex, 1, data.commitString );
114 m_branchList->SetItem( itemIndex, 2, lastUpdatedString );
115 }
116
117 m_branchList->SetColumnWidth( 0, wxLIST_AUTOSIZE );
118 m_branchList->SetColumnWidth( 1, wxLIST_AUTOSIZE );
119 m_branchList->SetColumnWidth( 2, wxLIST_AUTOSIZE );
120
121}
122
123
124void DIALOG_GIT_SWITCH::OnBranchListDClick( wxListEvent& aEvent )
125{
126 int selection = aEvent.GetIndex();
127
128 if( selection != wxNOT_FOUND )
129 {
130 wxString branchName = m_branchList->GetItemText( selection );
131 m_branchNameText->SetValue( branchName );
132
133 if( branchName != m_currentBranch )
134 EndModal( wxID_OK );
135 }
136}
137
138
140{
141 int selection = aEvent.GetIndex();
142
143 if( selection != wxNOT_FOUND )
144 {
145 wxString branchName = m_branchList->GetItemText( selection );
146 m_branchNameText->SetValue( branchName );
147 m_switchButton->SetLabel( _( "Switch" ) );
148 m_switchButton->Enable( branchName != m_currentBranch );
149 }
150 else
151 {
152 // Deselect all elements in the list
153 for( int ii = 0; ii < m_branchList->GetItemCount(); ++ii )
154 m_branchList->SetItemState( ii, 0, 0 );
155 }
156}
157
158void DIALOG_GIT_SWITCH::OnSwitchButton(wxCommandEvent& aEvent)
159{
160 wxString branchName = m_branchNameText->GetValue();
161
162 // Check if the branch name exists
163 bool branchExists = m_branches.count(branchName);
164
165 if (branchExists)
166 {
167 EndModal(wxID_OK); // Return Switch code
168 }
169 else
170 {
171 EndModal(wxID_ADD); // Return Add code
172 }
173}
174
175
176void DIALOG_GIT_SWITCH::OnCancelButton(wxCommandEvent& aEvent)
177{
178 EndModal(wxID_CANCEL); // Return Cancel code
179}
180
181
183{
184 return m_branchNameText->GetValue();
185}
186
187
189{
190 m_timer.Start( 500, true );
191}
192
193
195{
196 m_timer.Stop();
197}
198
199
200void DIALOG_GIT_SWITCH::OnTimer( wxTimerEvent& aEvt )
201{
202 wxString branchName = m_branchNameText->GetValue();
203
204 if( branchName == m_lastEnteredText )
205 return;
206
207 m_lastEnteredText = branchName;
208
209 // Check if the branch name exists
210 bool branchExists = m_branches.count( branchName );
211
212 if( branchExists )
213 {
214 m_switchButton->SetLabel( _( "Switch" ) );
215 m_switchButton->Enable( branchName != m_currentBranch );
216 }
217 else
218 {
219 m_switchButton->SetLabel( _( "Add" ) );
220 m_switchButton->Enable();
221 }
222}
223
224
225void DIALOG_GIT_SWITCH::OnTextChanged( wxCommandEvent& aEvt )
226{
227 StartTimer();
228}
229
230
232{
233 // Clear the branch list
234 m_branches.clear();
235
236 git_branch_iterator* branchIterator = nullptr;
237 git_branch_t branchType;
238
239 // Get Current Branch
240 git_reference* currentBranchReference = nullptr;
241 git_repository_head( &currentBranchReference, m_repository );
242
243 // Get the current branch name
244 if( currentBranchReference )
245 {
246 m_currentBranch = git_reference_shorthand( currentBranchReference );
247 git_reference_free( currentBranchReference );
248 }
249
250 // Initialize branch iterator
251 git_branch_iterator_new( &branchIterator, m_repository, GIT_BRANCH_ALL );
252
253 // Iterate over local branches
254 git_reference* branchReference = nullptr;
255 while( git_branch_next( &branchReference, &branchType, branchIterator ) == 0 )
256 {
257 // Get the branch OID
258 const git_oid* branchOid = git_reference_target( branchReference );
259
260 // Skip this branch if it doesn't have an OID
261 if( !branchOid )
262 {
263 git_reference_free( branchReference );
264 continue;
265 }
266
267 git_commit* commit = nullptr;
268
269 if( git_commit_lookup( &commit, m_repository, branchOid ) )
270 {
271 // Skip this branch if it doesn't have a commit
272 git_reference_free( branchReference );
273 continue;
274 }
275
276 // Retrieve commit details
277 BranchData branchData;
278 branchData.commitString = git_commit_message( commit );
279 branchData.lastUpdated = static_cast<time_t>( git_commit_time( commit ) );
280 branchData.isRemote = branchType == GIT_BRANCH_REMOTE;
281
282 m_branches[git_reference_shorthand( branchReference )] = branchData;
283
284 git_commit_free( commit );
285 git_reference_free( branchReference );
286 }
287
288 git_branch_iterator_free( branchIterator );
289}
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:88
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