KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_git_commit.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 The 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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "dialog_git_commit.h"
21
25
26#include <wx/button.h>
27#include <wx/checkbox.h>
28#include <wx/listctrl.h>
29#include <wx/sizer.h>
30#include <wx/stattext.h>
31#include <wx/textctrl.h>
32
33DIALOG_GIT_COMMIT::DIALOG_GIT_COMMIT( wxWindow* parent, git_repository* repo,
34 const wxString& defaultAuthorName,
35 const wxString& defaultAuthorEmail,
36 const std::map<wxString, int>& filesToCommit ) :
37 DIALOG_SHIM( parent, wxID_ANY, _( "Commit Changes" ) )
38{
39 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
40
41
42 // List Control for files to commit
43 m_listCtrl = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT );
44
45 // Set up columns
46 m_listCtrl->EnableCheckBoxes();
47 m_listCtrl->AppendColumn( _( "Filename" ) );
48 m_listCtrl->AppendColumn( _( "Status" ) );
49
50 // Set column widths
51 m_listCtrl->SetColumnWidth( 0, 200 );
52 m_listCtrl->SetColumnWidth( 1, 200 );
53
54 // Set up image list for icons
55#ifdef __WXMAC__
56 // HiDPI-aware API; will be generally available in wxWidgets 3.4
57 wxVector<wxBitmapBundle> stateImages;
58 stateImages.push_back( wxBitmapBundle() ); // GIT_STATUS_UNTRACKED
59 stateImages.push_back( KiBitmapBundle( BITMAPS::git_good_check ) ); // GIT_STATUS_CURRENT
60 stateImages.push_back( KiBitmapBundle( BITMAPS::git_modified ) ); // GIT_STATUS_MODIFIED
61 stateImages.push_back( KiBitmapBundle( BITMAPS::git_add ) ); // GIT_STATUS_ADDED
62 stateImages.push_back( KiBitmapBundle( BITMAPS::git_delete ) ); // GIT_STATUS_DELETED
63 stateImages.push_back( KiBitmapBundle( BITMAPS::git_out_of_date ) ); // GIT_STATUS_BEHIND
64 stateImages.push_back( KiBitmapBundle( BITMAPS::git_changed_ahead ) ); // GIT_STATUS_AHEAD
65 stateImages.push_back( KiBitmapBundle( BITMAPS::git_conflict ) ); // GIT_STATUS_CONFLICTED
66
67 m_listCtrl->SetNormalImages( stateImages );
68 m_listCtrl->SetSmallImages( stateImages );
69#else
70 wxImageList* imageList = new wxImageList(
71 16, 16, true, static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_LAST ) );
72
73 imageList->Add( KiBitmap( BITMAPS::git_good_check ) ); // PLACEHOLDER
74 imageList->Add( KiBitmap( BITMAPS::git_good_check ) ); // GIT_STATUS_CURRENT
75 imageList->Add( KiBitmap( BITMAPS::git_modified ) ); // GIT_STATUS_MODIFIED
76 imageList->Add( KiBitmap( BITMAPS::git_add ) ); // GIT_STATUS_ADDED
77 imageList->Add( KiBitmap( BITMAPS::git_delete ) ); // GIT_STATUS_DELETED
78 imageList->Add( KiBitmap( BITMAPS::git_out_of_date ) ); // GIT_STATUS_BEHIND
79 imageList->Add( KiBitmap( BITMAPS::git_changed_ahead ) ); // GIT_STATUS_AHEAD
80 imageList->Add( KiBitmap( BITMAPS::git_conflict ) ); // GIT_STATUS_CONFLICTED
81
82 // Assign the image list to the list control
83 m_listCtrl->SetImageList( imageList, wxIMAGE_LIST_SMALL );
84#endif
85
86 // Populate list control with items
87 for( auto& [filename, status] : filesToCommit )
88 {
89 int i = m_listCtrl->GetItemCount();
90 m_listCtrl->InsertItem( i, filename );
91
92 if( status & ( GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_NEW ) )
93 {
94 m_listCtrl->SetItem( i, 1, _( "New" ) );
95 m_listCtrl->SetItemImage(
96 i, static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_ADDED ) );
97
98 if( status & ( GIT_STATUS_INDEX_NEW ) )
99 m_listCtrl->CheckItem( i, true );
100 }
101 else if( status & ( GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED ) )
102 {
103 m_listCtrl->SetItem( i, 1, _( "Modified" ) );
104 m_listCtrl->SetItemImage(
105 i, static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ) );
106
107 if( status & ( GIT_STATUS_INDEX_MODIFIED ) )
108 m_listCtrl->CheckItem( i, true );
109 }
110 else if( status & ( GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_DELETED ) )
111 {
112 m_listCtrl->SetItem( i, 1, _( "Deleted" ) );
113 m_listCtrl->SetItemImage(
114 i, static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_DELETED ) );
115
116 if( status & ( GIT_STATUS_INDEX_DELETED ) )
117 m_listCtrl->CheckItem( i, true );
118 }
119 else
120 {
121 printf( " Unknown status: %d\n", status );
122 }
123 }
124
125 sizer->Add( m_listCtrl, 1, wxEXPAND | wxALL, 5 );
126
127 // Commit Message Text Control
128 wxStaticText* commitMessageLabel = new wxStaticText( this, wxID_ANY, _( "Commit Message:" ) );
130 new wxTextCtrl( this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
131
133
134 sizer->Add( commitMessageLabel, 0, wxALL, 5 );
135 sizer->Add( m_commitMessageTextCtrl, 1, wxEXPAND | wxALL, 5 );
136
137 // Author Name and Email Text Control
138 wxStaticText* authorLabel = new wxStaticText( this, wxID_ANY, _( "Author:" ) );
139 wxString defaultAuthor = defaultAuthorName + " <" + defaultAuthorEmail + ">";
141 new wxTextCtrl( this, wxID_ANY, defaultAuthor, wxDefaultPosition, wxDefaultSize, 0 );
142 sizer->Add( authorLabel, 0, wxALL, 5 );
143 sizer->Add( m_authorTextCtrl, 0, wxEXPAND | wxALL, 5 );
144
145 // OK and Cancel Buttons
146
147 wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer();
148
149 m_okButton = new wxButton( this, wxID_OK, _( "OK" ) );
150 wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
151 buttonSizer->Add( cancelButton, 0, wxALL, 5 );
152 buttonSizer->Add( m_okButton, 0, wxALL, 5 );
153 buttonSizer->Realize();
154
155 sizer->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 5 );
156
157 SetSizerAndFit( sizer );
158
159 SetupStandardButtons( { { wxID_OK, _( "C&ommit" ) } } );
160
161 // Bind events
162 Bind( wxEVT_TEXT, &DIALOG_GIT_COMMIT::OnTextChanged, this, m_commitMessageTextCtrl->GetId() );
163 Bind( wxEVT_LIST_ITEM_CHECKED, &DIALOG_GIT_COMMIT::OnItemChecked, this, m_listCtrl->GetId() );
164 Bind( wxEVT_LIST_ITEM_UNCHECKED, &DIALOG_GIT_COMMIT::OnItemUnchecked, this, m_listCtrl->GetId() );
165
166 // Set the repository and defaults
167 m_repo = repo;
168 m_defaultAuthorName = defaultAuthorName;
169 m_defaultAuthorEmail = defaultAuthorEmail;
170}
171
172
173void DIALOG_GIT_COMMIT::OnTextChanged( wxCommandEvent& aEvent )
174{
175 if( m_commitMessageTextCtrl->GetValue().IsEmpty() )
176 {
177 m_okButton->Disable();
178 m_okButton->SetToolTip( _( "Commit message cannot be empty" ) );
179 }
180 else
181 {
182 m_okButton->Enable();
183 m_okButton->SetToolTip( wxEmptyString );
184 }
185}
186
187
189{
190 return m_commitMessageTextCtrl->GetValue();
191}
192
193
194void DIALOG_GIT_COMMIT::SetCommitMessage( const wxString& aMessage )
195{
196 m_commitMessageTextCtrl->SetValue( aMessage );
197}
198
199
201{
202 wxString authorText = m_authorTextCtrl->GetValue();
203 size_t pos = authorText.find( '<' );
204
205 if( pos != wxString::npos )
206 return authorText.substr( 0, pos ).Trim();
207
208 return wxEmptyString;
209}
210
211
213{
214 wxString authorText = m_authorTextCtrl->GetValue();
215 size_t startPos = authorText.find( '<' );
216 size_t endPos = authorText.find( '>' );
217
218 if( startPos != wxString::npos && endPos != wxString::npos && startPos < endPos )
219 return authorText.substr( startPos + 1, endPos - startPos - 1 ).Trim();
220
221 return wxEmptyString;
222}
223
224
225std::vector<wxString> DIALOG_GIT_COMMIT::GetSelectedFiles() const
226{
227 std::vector<wxString> selectedFiles;
228
229 long item = -1;
230
231 while( ( item = m_listCtrl->GetNextItem( item, wxLIST_NEXT_ALL ) ) != -1 )
232 {
233 if( m_listCtrl->IsItemChecked( item ) )
234 selectedFiles.push_back( m_listCtrl->GetItemText( item ) );
235 }
236
237 return selectedFiles;
238}
239
240
241void DIALOG_GIT_COMMIT::OnItemChecked( wxListEvent& aEvent )
242{
243 long checkedItem = aEvent.GetIndex();
244
245 if( m_listCtrl->GetItemState( checkedItem, wxLIST_STATE_SELECTED ) )
246 {
247 long item = -1;
248
249 while( ( item = m_listCtrl->GetNextItem( item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ) ) != -1 )
250 {
251 if( item != checkedItem )
252 m_listCtrl->CheckItem( item, true );
253 }
254 }
255}
256
257
258void DIALOG_GIT_COMMIT::OnItemUnchecked( wxListEvent& aEvent )
259{
260 long uncheckedItem = aEvent.GetIndex();
261
262 if( m_listCtrl->GetItemState( uncheckedItem, wxLIST_STATE_SELECTED ) )
263 {
264 long item = -1;
265
266 while( ( item = m_listCtrl->GetNextItem( item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ) ) != -1 )
267 {
268 if( item != uncheckedItem )
269 m_listCtrl->CheckItem( item, false );
270 }
271 }
272}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:100
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
@ git_out_of_date
@ git_changed_ahead
wxTextCtrl * m_commitMessageTextCtrl
void OnTextChanged(wxCommandEvent &event)
wxString GetCommitMessage() const
wxTextCtrl * m_authorTextCtrl
DIALOG_GIT_COMMIT(wxWindow *parent, git_repository *repo, const wxString &defaultAuthorName, const wxString &defaultAuthorEmail, const std::map< wxString, int > &filesToCommit)
void OnItemChecked(wxListEvent &event)
void SetCommitMessage(const wxString &aMessage)
Pre-fill the commit message.
void OnItemUnchecked(wxListEvent &event)
wxString GetAuthorEmail() const
git_repository * m_repo
std::vector< wxString > GetSelectedFiles() const
wxString GetAuthorName() const
wxListCtrl * m_listCtrl
void OptOut(wxWindow *aWindow)
Opt out of control state saving.
void SetupStandardButtons(std::map< int, wxString > aLabels={})
DIALOG_SHIM(wxWindow *aParent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER, const wxString &name=wxDialogNameStr)
#define _(s)