Fixed issue #4126: Capitalize the first letter in the Push dialog
[TortoiseGit.git] / src / TortoiseProc / RefLogDlg.cpp
blobfd74112cdd276f77c718c9979af18a318c4ce02b
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009-2021, 2023-2024 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // RefLogDlg.cpp : implementation file
22 #include "stdafx.h"
23 #include "resource.h"
24 #include "RefLogDlg.h"
25 #include "Git.h"
26 #include "AppUtils.h"
27 #include "MessageBox.h"
28 #include "UnicodeUtils.h"
30 // CRefLogDlg dialog
32 IMPLEMENT_DYNAMIC(CRefLogDlg, CResizableStandAloneDialog)
34 UINT CRefLogDlg::m_FindDialogMessage = ::RegisterWindowMessage(FINDMSGSTRING);
36 CRefLogDlg::CRefLogDlg(CWnd* pParent /*=nullptr*/)
37 : CResizableStandAloneDialog(CRefLogDlg::IDD, pParent)
41 CRefLogDlg::~CRefLogDlg()
45 void CRefLogDlg::DoDataExchange(CDataExchange* pDX)
47 CDialog::DoDataExchange(pDX);
48 DDX_Control(pDX, IDC_COMBOBOXEX_REF, m_ChooseRef);
49 DDX_Control(pDX, IDC_REFLOG_LIST, m_RefList);
53 BEGIN_MESSAGE_MAP(CRefLogDlg, CResizableStandAloneDialog)
54 ON_BN_CLICKED(IDOK, &CRefLogDlg::OnBnClickedOk)
55 ON_BN_CLICKED(IDC_REFLOG_BUTTONCLEARSTASH, &CRefLogDlg::OnBnClickedClearStash)
56 ON_CBN_SELCHANGE(IDC_COMBOBOXEX_REF, &CRefLogDlg::OnCbnSelchangeRef)
57 ON_NOTIFY(LVN_ITEMCHANGED, IDC_REFLOG_LIST, OnLvnItemchangedRefLoglist)
58 ON_MESSAGE(MSG_REFLOG_CHANGED,OnRefLogChanged)
59 ON_REGISTERED_MESSAGE(m_FindDialogMessage, OnFindDialogMessage)
60 ON_BN_CLICKED(IDC_SEARCH, OnFind)
61 END_MESSAGE_MAP()
63 LRESULT CRefLogDlg::OnRefLogChanged(WPARAM /*wParam*/, LPARAM /*lParam*/)
65 OnCbnSelchangeRef();
66 return 0;
69 BOOL CRefLogDlg::OnInitDialog()
71 CResizableStandAloneDialog::OnInitDialog();
72 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
74 AddAnchor(IDOK,BOTTOM_RIGHT);
75 AddAnchor(IDCANCEL,BOTTOM_RIGHT);
76 AddAnchor(IDC_REFLOG_BUTTONCLEARSTASH, BOTTOM_LEFT);
77 AddAnchor(IDC_SEARCH, BOTTOM_LEFT);
78 AddAnchor(IDC_REFLOG_LIST,TOP_LEFT,BOTTOM_RIGHT);
79 AddAnchor(IDHELP, BOTTOM_RIGHT);
80 AddAnchor(IDC_COMBOBOXEX_REF, TOP_LEFT, TOP_RIGHT);
82 AddOthersToAnchor();
83 this->EnableSaveRestore(L"RefLogDlg");
85 CAppUtils::SetWindowTitle(*this, g_Git.m_CurrentDir);
87 m_ChooseRef.SetMaxHistoryItems(0x7FFFFFFF);
89 m_RefList.m_hasWC = !GitAdminDir::IsBareRepo(g_Git.m_CurrentDir);
91 this->m_RefList.InsertRefLogColumn();
93 Refresh();
95 return TRUE;
97 // CRefLogDlg message handlers
99 void CRefLogDlg::OnBnClickedOk()
101 if (m_RefList.GetSelectedCount() == 1)
103 // get the selected row
104 POSITION pos = m_RefList.GetFirstSelectedItemPosition();
105 size_t selIndex = m_RefList.GetNextSelectedItem(pos);
106 if (selIndex < m_RefList.m_arShownList.size())
108 // all ok, pick up the revision
109 GitRev* pLogEntry = m_RefList.m_arShownList.SafeGetAt(selIndex);
110 // extract the hash
111 m_SelectedHash = pLogEntry->m_CommitHash;
115 OnOK();
117 void CRefLogDlg::OnBnClickedClearStash()
119 size_t count = m_RefList.m_arShownList.size();
120 CString msg;
121 msg.Format(IDS_PROC_DELETEALLSTASH, count);
122 if (CMessageBox::Show(this->GetSafeHwnd(), msg, L"TortoiseGit", 2, IDI_QUESTION, CString(MAKEINTRESOURCE(IDS_DELETEBUTTON)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON))) == 1)
124 CString cmdOut;
125 if (g_Git.Run(L"git.exe stash clear", &cmdOut, CP_UTF8))
127 MessageBox(cmdOut, L"TortoiseGit", MB_ICONERROR);
128 return;
131 OnCbnSelchangeRef();
135 void CRefLogDlg::OnCbnSelchangeRef()
137 m_CurrentBranch = m_ChooseRef.GetString(); // remember selected branch
138 m_RefList.m_CurrentBranch = m_CurrentBranch;
139 m_RefList.m_RevCache.clear();
140 m_RefList.ClearText();
141 m_RefList.SetRedraw(false);
143 if (CString err; GitRevLoglist::GetRefLog(m_CurrentBranch, m_RefList.m_RevCache, err))
144 MessageBox(L"Error while loading reflog.\n" + err, L"TortoiseGit", MB_ICONERROR);
146 m_RefList.SetItemCountEx(static_cast<int>(m_RefList.m_RevCache.size()));
148 this->m_RefList.m_arShownList.clear();
150 for (unsigned int i = 0; i < m_RefList.m_RevCache.size(); ++i)
152 GitRevLoglist* rev = &m_RefList.m_RevCache[i];
153 this->m_RefList.m_arShownList.SafeAdd(rev);
156 m_RefList.SetRedraw(true);
158 m_RefList.Invalidate();
160 // reset search start positions
161 m_RefList.m_nSearchIndex = 0;
162 m_nSearchLine = 0;
164 if (m_CurrentBranch == L"refs/stash")
166 GetDlgItem(IDC_REFLOG_BUTTONCLEARSTASH)->ShowWindow(SW_SHOW);
167 const BOOL enabled = !m_RefList.m_arShownList.empty();
168 GetDlgItem(IDC_REFLOG_BUTTONCLEARSTASH)->EnableWindow(enabled);
169 if (!enabled)
170 GetDlgItem(IDOK)->SetFocus();
172 else
174 GetDlgItem(IDC_REFLOG_BUTTONCLEARSTASH)->ShowWindow(SW_HIDE);
175 GetDlgItem(IDC_REFLOG_BUTTONCLEARSTASH)->EnableWindow(FALSE);
179 BOOL CRefLogDlg::PreTranslateMessage(MSG* pMsg)
181 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F5)
182 Refresh();
183 else if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_F3 || (pMsg->wParam == 'F' && (GetAsyncKeyState(VK_CONTROL) & 0x8000))))
184 OnFind();
186 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
189 void CRefLogDlg::OnLvnItemchangedRefLoglist(NMHDR* pNMHDR, LRESULT* pResult)
191 auto pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
192 *pResult = 0;
193 if (pNMLV->iItem < 0)
194 return;
195 m_RefList.m_nSearchIndex = pNMLV->iItem;
196 m_nSearchLine = pNMLV->iItem;
199 void CRefLogDlg::Refresh()
201 STRING_VECTOR list;
202 list.push_back(L"HEAD");
203 if (g_Git.GetRefList(list))
204 MessageBox(g_Git.GetGitLastErr(L"Could not get all refs."), L"TortoiseGit", MB_ICONERROR);
206 m_ChooseRef.SetList(list);
208 if (m_CurrentBranch.IsEmpty())
209 m_CurrentBranch = L"HEAD";
211 bool found = false;
212 for (int i = 0; i < static_cast<int>(list.size()); ++i)
214 if (list[i] == m_CurrentBranch)
216 m_ChooseRef.SetCurSel(i);
217 found = true;
218 break;
221 if (!found)
222 m_ChooseRef.SetCurSel(0); /* Choose HEAD */
224 OnCbnSelchangeRef();
227 void CRefLogDlg::OnFind()
229 if (m_pFindDialog)
231 m_pFindDialog->SetFocus();
232 return;
234 m_pFindDialog = new CFindReplaceDialog();
235 m_pFindDialog->Create(TRUE, L"", nullptr, FR_DOWN | FR_HIDEWHOLEWORD | FR_HIDEUPDOWN, this);
236 CTheme::Instance().SetThemeForDialog(m_pFindDialog->GetSafeHwnd(), CTheme::Instance().IsDarkTheme());
239 LRESULT CRefLogDlg::OnFindDialogMessage(WPARAM /*wParam*/, LPARAM /*lParam*/)
241 ASSERT(m_pFindDialog);
243 if (m_RefList.m_arShownList.empty())
244 return 0;
246 // If the FR_DIALOGTERM flag is set,
247 // invalidate the handle identifying the dialog box.
248 if (m_pFindDialog->IsTerminating())
250 m_pFindDialog = nullptr;
251 return 0;
254 // If the FR_FINDNEXT flag is set,
255 // call the application-defined search routine
256 // to search for the requested string.
257 if (m_pFindDialog->FindNext())
259 //read data from dialog
260 CString findString = m_pFindDialog->GetFindString();
262 bool bFound = false;
263 const bool bCaseSensitive = !!(m_pFindDialog->MatchCase());
265 if (!bCaseSensitive)
266 findString.MakeLower();
268 size_t i = m_nSearchLine;
269 if (i >= m_RefList.m_arShownList.size())
271 i = 0;
272 m_pFindDialog->FlashWindowEx(FLASHW_ALL, 2, 100);
277 GitRevLoglist* data = m_RefList.m_arShownList.SafeGetAt(i);
279 CString str;
280 str += data->m_Ref;
281 str += L'\n';
282 str += data->m_RefAction;
283 str += L'\n';
284 str += data->m_CommitHash.ToString();
285 str += L'\n';
286 str += data->GetSubject();
287 str += L'\n';
288 str += data->GetBody();
289 str += L'\n';
291 if (!bCaseSensitive)
292 str.MakeLower();
294 if (str.Find(findString) >= 0)
295 bFound = true;
297 ++i;
298 if(!bFound && i >= m_RefList.m_arShownList.size())
299 i=0;
300 } while (i != m_nSearchLine && (!bFound));
302 if (bFound)
304 m_RefList.SetHotItem(static_cast<int>(i) - 1);
305 m_RefList.EnsureVisible(static_cast<int>(i) - 1, FALSE);
306 m_nSearchLine = i;
308 else
309 MessageBox(L'"' + findString + L"\" " + CString(MAKEINTRESOURCE(IDS_NOTFOUND)), L"TortoiseGit", MB_ICONINFORMATION);
312 return 0;