Do not always include staged files
[TortoiseGit.git] / src / TortoiseProc / ChangedDlg.cpp
blob3f58ee5c826e03cf595c9f4632fec682e926b170
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2018 - TortoiseGit
4 // Copyright (C) 2003-2008 - TortoiseSVN
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 2
9 // of the License, or (at your option) any later version.
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.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "ChangedDlg.h"
23 #include "MessageBox.h"
24 #include "cursor.h"
25 #include "AppUtils.h"
26 #include "ChangedDlg.h"
27 #include "IconMenu.h"
28 #include "RefLogDlg.h"
30 IMPLEMENT_DYNAMIC(CChangedDlg, CResizableStandAloneDialog)
31 CChangedDlg::CChangedDlg(CWnd* pParent /*=nullptr*/)
32 : CResizableStandAloneDialog(CChangedDlg::IDD, pParent)
33 , m_bShowUnversioned(FALSE)
34 , m_iShowUnmodified(0)
35 , m_bBlock(FALSE)
36 , m_bCanceled(false)
37 , m_bShowIgnored(FALSE)
38 , m_bShowLocalChangesIgnored(FALSE)
39 , m_bWholeProject(FALSE)
40 , m_bRemote(FALSE)
41 , m_bShowStaged(TRUE)
45 CChangedDlg::~CChangedDlg()
49 void CChangedDlg::DoDataExchange(CDataExchange* pDX)
51 CResizableStandAloneDialog::DoDataExchange(pDX);
52 DDX_Control(pDX, IDC_CHANGEDLIST, m_FileListCtrl);
53 DDX_Control(pDX, IDC_BUTTON_STASH, m_ctrlStash);
54 DDX_Check(pDX, IDC_SHOWUNVERSIONED, m_bShowUnversioned);
55 DDX_Check(pDX, IDC_SHOWUNMODIFIED, m_iShowUnmodified);
56 DDX_Check(pDX, IDC_SHOWIGNORED, m_bShowIgnored);
57 DDX_Check(pDX, IDC_SHOWLOCALCHANGESIGNORED, m_bShowLocalChangesIgnored);
58 DDX_Check(pDX, IDC_WHOLE_PROJECT, m_bWholeProject);
59 DDX_Check(pDX, IDC_SHOWSTAGED, m_bShowStaged);
63 BEGIN_MESSAGE_MAP(CChangedDlg, CResizableStandAloneDialog)
64 ON_BN_CLICKED(IDC_SHOWUNVERSIONED, OnBnClickedShowunversioned)
65 ON_BN_CLICKED(IDC_SHOWUNMODIFIED, OnBnClickedShowUnmodified)
66 ON_REGISTERED_MESSAGE(CGitStatusListCtrl::GITSLNM_NEEDSREFRESH, OnSVNStatusListCtrlNeedsRefresh)
67 ON_REGISTERED_MESSAGE(CGitStatusListCtrl::GITSLNM_ITEMCOUNTCHANGED, OnSVNStatusListCtrlItemCountChanged)
68 ON_BN_CLICKED(IDC_SHOWIGNORED, &CChangedDlg::OnBnClickedShowignored)
69 ON_BN_CLICKED(IDC_REFRESH, &CChangedDlg::OnBnClickedRefresh)
70 ON_BN_CLICKED(IDC_COMMIT, &CChangedDlg::OnBnClickedCommit)
71 ON_BN_CLICKED(IDC_BUTTON_STASH, &CChangedDlg::OnBnClickedStash)
72 ON_BN_CLICKED(IDC_BUTTON_UNIFIEDDIFF, &CChangedDlg::OnBnClickedButtonUnifieddiff)
73 ON_BN_CLICKED(IDC_SHOWLOCALCHANGESIGNORED, &CChangedDlg::OnBnClickedShowlocalchangesignored)
74 ON_BN_CLICKED(IDC_WHOLE_PROJECT, OnBnClickedWholeProject)
75 ON_BN_CLICKED(IDC_SHOWSTAGED, OnBnClickedShowStaged)
76 END_MESSAGE_MAP()
78 BOOL CChangedDlg::OnInitDialog()
80 CResizableStandAloneDialog::OnInitDialog();
82 m_regAddBeforeCommit = CRegDWORD(L"Software\\TortoiseGit\\AddBeforeCommit", TRUE);
83 m_bShowUnversioned = m_regAddBeforeCommit;
85 CString regPath(g_Git.m_CurrentDir);
86 regPath.Replace(L':', L'_');
87 m_regShowWholeProject = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\ShowWholeProject\\" + regPath, FALSE);
88 m_bWholeProject = m_regShowWholeProject;
89 m_regShowStaged = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\ChangedFilesIncludeStaged", TRUE);
90 m_bShowStaged = m_regShowStaged;
91 SetDlgTitle();
93 if (m_pathList.GetCount() == 1 && m_pathList[0].GetWinPathString().IsEmpty())
95 m_bWholeProject = BST_CHECKED;
96 DialogEnableWindow(IDC_WHOLE_PROJECT, FALSE);
99 UpdateData(FALSE);
101 m_FileListCtrl.Init(GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD| GITSLC_COLDEL | GITSLC_COLMODIFICATIONDATE, L"ChangedDlg", (GITSLC_POPALL ^ (GITSLC_POPSAVEAS | GITSLC_POPRESTORE | GITSLC_POPPREPAREDIFF)), false);
102 m_FileListCtrl.SetCancelBool(&m_bCanceled);
103 m_FileListCtrl.SetBackgroundImage(IDI_CFM_BKG);
104 m_FileListCtrl.SetEmptyString(IDS_REPOSTATUS_EMPTYFILELIST);
106 AdjustControlSize(IDC_SHOWUNVERSIONED);
107 AdjustControlSize(IDC_SHOWUNMODIFIED);
108 AdjustControlSize(IDC_SHOWLOCALCHANGESIGNORED);
109 AdjustControlSize(IDC_SHOWIGNORED);
110 AdjustControlSize(IDC_WHOLE_PROJECT);
111 AdjustControlSize(IDC_SHOWSTAGED);
113 AddAnchor(IDC_CHANGEDLIST, TOP_LEFT, BOTTOM_RIGHT);
114 AddAnchor(IDC_SUMMARYTEXT, BOTTOM_LEFT, BOTTOM_RIGHT);
115 AddAnchor(IDC_SHOWUNVERSIONED, BOTTOM_LEFT);
116 AddAnchor(IDC_SHOWUNMODIFIED, BOTTOM_LEFT);
117 AddAnchor(IDC_SHOWLOCALCHANGESIGNORED, BOTTOM_LEFT);
118 AddAnchor(IDC_SHOWIGNORED, BOTTOM_LEFT);
119 AddAnchor(IDC_WHOLE_PROJECT, BOTTOM_LEFT);
120 AddAnchor(IDC_SHOWSTAGED, BOTTOM_LEFT);
121 AddAnchor(IDC_INFOLABEL, BOTTOM_RIGHT);
122 AddAnchor(IDC_BUTTON_STASH, BOTTOM_RIGHT);
123 AddAnchor(IDC_BUTTON_UNIFIEDDIFF, BOTTOM_RIGHT);
124 AddAnchor(IDC_COMMIT, BOTTOM_RIGHT);
125 AddAnchor(IDC_REFRESH, BOTTOM_RIGHT);
126 AddAnchor(IDOK, BOTTOM_RIGHT);
127 // SetPromptParentWindow(m_hWnd);
128 if (GetExplorerHWND())
129 CenterWindow(CWnd::FromHandle(GetExplorerHWND()));
130 EnableSaveRestore(L"ChangedDlg");
132 m_ctrlStash.m_bAlwaysShowArrow = true;
134 m_bRemote = !!(DWORD)CRegDWORD(L"Software\\TortoiseGit\\CheckRepo", FALSE);
136 // first start a thread to obtain the status without
137 // blocking the dialog
138 if (!AfxBeginThread(ChangedStatusThreadEntry, this))
140 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
143 return TRUE;
146 UINT CChangedDlg::ChangedStatusThreadEntry(LPVOID pVoid)
148 return reinterpret_cast<CChangedDlg*>(pVoid)->ChangedStatusThread();
151 UINT CChangedDlg::ChangedStatusThread()
153 InterlockedExchange(&m_bBlock, TRUE);
155 m_bCanceled = false;
156 SetDlgItemText(IDOK, CString(MAKEINTRESOURCE(IDS_MSGBOX_CANCEL)));
157 DialogEnableWindow(IDC_REFRESH, FALSE);
158 DialogEnableWindow(IDC_SHOWUNVERSIONED, FALSE);
159 DialogEnableWindow(IDC_SHOWUNMODIFIED, FALSE);
160 DialogEnableWindow(IDC_SHOWIGNORED, FALSE);
161 DialogEnableWindow(IDC_SHOWLOCALCHANGESIGNORED, FALSE);
162 DialogEnableWindow(IDC_SHOWSTAGED, FALSE);
164 g_Git.RefreshGitIndex();
166 m_FileListCtrl.StoreScrollPos();
167 m_FileListCtrl.Clear();
168 m_FileListCtrl.m_bIncludedStaged = (m_bShowStaged == TRUE);
169 if (!m_FileListCtrl.GetStatus(m_bWholeProject ? nullptr : &m_pathList, m_bRemote, m_bShowIgnored != FALSE, m_bShowUnversioned != FALSE, m_bShowLocalChangesIgnored != FALSE))
171 if (!m_FileListCtrl.GetLastErrorMessage().IsEmpty())
172 m_FileListCtrl.SetEmptyString(m_FileListCtrl.GetLastErrorMessage());
174 unsigned int dwShow = GITSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALS | GITSLC_SHOWSWITCHED | GITSLC_SHOWINCHANGELIST;
175 dwShow |= m_bShowUnversioned ? GITSLC_SHOWUNVERSIONED : 0;
176 dwShow |= m_iShowUnmodified ? GITSLC_SHOWNORMAL : 0;
177 dwShow |= m_bShowIgnored ? GITSLC_SHOWIGNORED : 0;
178 dwShow |= m_bShowLocalChangesIgnored ? GITSLC_SHOWASSUMEVALID | GITSLC_SHOWSKIPWORKTREE : 0;
179 m_FileListCtrl.Show(dwShow);
180 UpdateStatistics();
182 SetDlgTitle();
183 bool bIsDirectory = false;
184 if (m_pathList.GetCount() == 1)
185 bIsDirectory = m_pathList[0].IsDirectory() || m_pathList[0].IsEmpty(); // if it is empty it is g_Git.m_CurrentDir which is a directory
187 SetDlgItemText(IDOK, CString(MAKEINTRESOURCE(IDS_MSGBOX_OK)));
188 DialogEnableWindow(IDC_REFRESH, TRUE);
189 DialogEnableWindow(IDC_SHOWUNVERSIONED, bIsDirectory);
190 //DialogEnableWindow(IDC_SHOWUNMODIFIED, bIsDirectory);
191 DialogEnableWindow(IDC_SHOWIGNORED, bIsDirectory);
192 DialogEnableWindow(IDC_SHOWLOCALCHANGESIGNORED, TRUE);
193 DialogEnableWindow(IDC_SHOWSTAGED, TRUE);
194 InterlockedExchange(&m_bBlock, FALSE);
195 // revert the remote flag back to the default
196 m_bRemote = !!(DWORD)CRegDWORD(L"Software\\TortoiseGit\\CheckRepo", FALSE);
197 RefreshCursor();
198 return 0;
201 void CChangedDlg::OnOK()
203 if (m_bBlock)
205 m_bCanceled = true;
206 return;
208 __super::OnOK();
211 void CChangedDlg::OnCancel()
213 if (m_bBlock)
215 m_bCanceled = true;
216 return;
218 __super::OnCancel();
221 DWORD CChangedDlg::UpdateShowFlags()
223 DWORD dwShow = m_FileListCtrl.GetShowFlags();
224 if (m_bShowUnversioned)
225 dwShow |= GITSLC_SHOWUNVERSIONED;
226 else
227 dwShow &= ~GITSLC_SHOWUNVERSIONED;
228 if (m_iShowUnmodified)
229 dwShow |= GITSLC_SHOWNORMAL;
230 else
231 dwShow &= ~GITSLC_SHOWNORMAL;
232 if (m_bShowIgnored)
233 dwShow |= GITSLC_SHOWIGNORED;
234 else
235 dwShow &= ~GITSLC_SHOWIGNORED;
236 if (m_bShowLocalChangesIgnored)
237 dwShow |= GITSLC_SHOWASSUMEVALID|GITSLC_SHOWSKIPWORKTREE;
238 else
239 dwShow &= ~(GITSLC_SHOWASSUMEVALID|GITSLC_SHOWSKIPWORKTREE);
241 // old bShowExternals:
242 dwShow &= ~(GITSLC_SHOWEXTERNAL | GITSLC_SHOWINEXTERNALS | GITSLC_SHOWEXTERNALFROMDIFFERENTREPO);
244 return dwShow;
247 void CChangedDlg::SetDlgTitle()
249 if (m_sTitle.IsEmpty())
250 GetWindowText(m_sTitle);
252 if (m_bWholeProject)
253 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, m_sTitle);
254 else
256 if (m_pathList.GetCount() == 1)
257 CAppUtils::SetWindowTitle(m_hWnd, g_Git.CombinePath(m_pathList[0].GetUIPathString()), m_sTitle);
258 else
259 CAppUtils::SetWindowTitle(m_hWnd, g_Git.CombinePath(m_FileListCtrl.GetCommonDirectory(false)), m_sTitle);
263 void CChangedDlg::OnBnClickedShowunversioned()
265 UpdateData();
266 m_regAddBeforeCommit = m_bShowUnversioned;
267 if(m_FileListCtrl.m_FileLoaded & CGitStatusListCtrl::FILELIST_UNVER)
269 m_FileListCtrl.StoreScrollPos();
270 m_FileListCtrl.Show(UpdateShowFlags());
272 else
274 if(m_bShowUnversioned)
276 if (!AfxBeginThread(ChangedStatusThreadEntry, this))
277 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
280 UpdateStatistics();
283 void CChangedDlg::OnBnClickedShowUnmodified()
285 UpdateData();
286 m_FileListCtrl.StoreScrollPos();
287 m_FileListCtrl.Show(UpdateShowFlags());
288 m_regAddBeforeCommit = m_bShowUnversioned;
289 UpdateStatistics();
292 void CChangedDlg::OnBnClickedShowignored()
294 UpdateData();
295 m_FileListCtrl.StoreScrollPos();
296 if (m_FileListCtrl.m_FileLoaded & CGitStatusListCtrl::FILELIST_IGNORE)
297 m_FileListCtrl.Show(UpdateShowFlags());
298 else if (m_bShowIgnored)
300 if (!AfxBeginThread(ChangedStatusThreadEntry, this))
301 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
303 UpdateStatistics();
306 void CChangedDlg::OnBnClickedShowlocalchangesignored()
308 UpdateData();
309 m_FileListCtrl.StoreScrollPos();
310 if (m_FileListCtrl.m_FileLoaded & CGitStatusListCtrl::FILELIST_LOCALCHANGESIGNORED)
311 m_FileListCtrl.Show(UpdateShowFlags());
312 else if (m_bShowLocalChangesIgnored)
314 if (!AfxBeginThread(ChangedStatusThreadEntry, this))
315 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
317 UpdateStatistics();
320 LRESULT CChangedDlg::OnSVNStatusListCtrlNeedsRefresh(WPARAM, LPARAM)
322 if (!AfxBeginThread(ChangedStatusThreadEntry, this))
323 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
324 return 0;
327 LRESULT CChangedDlg::OnSVNStatusListCtrlItemCountChanged(WPARAM, LPARAM)
329 UpdateStatistics();
330 return 0;
333 BOOL CChangedDlg::PreTranslateMessage(MSG* pMsg)
335 if (pMsg->message == WM_KEYDOWN)
337 switch (pMsg->wParam)
339 case VK_F5:
341 if (m_bBlock)
342 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
343 if (!AfxBeginThread(ChangedStatusThreadEntry, this))
345 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
348 break;
352 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
355 void CChangedDlg::OnBnClickedRefresh()
357 if (!m_bBlock)
359 if (!AfxBeginThread(ChangedStatusThreadEntry, this))
360 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
364 void CChangedDlg::UpdateStatistics()
366 CString temp = m_FileListCtrl.GetStatisticsString();
367 temp.Replace(L" = ", L"=");
368 temp.Replace(L"\n", L", ");
369 SetDlgItemText(IDC_INFOLABEL, temp);
372 void CChangedDlg::OnBnClickedCommit()
374 CTGitPathList pathList;
375 bool bSingleFile = (m_pathList.GetCount() >= 1 && !m_pathList[0].IsEmpty() && !m_pathList[0].IsDirectory());
376 if (bSingleFile)
377 pathList.AddPath(m_pathList[0]);
378 else
379 pathList.AddPath(m_pathList.GetCommonRoot().GetDirectory());
381 bool bSelectFilesForCommit = !!DWORD(CRegStdDWORD(L"Software\\TortoiseGit\\SelectFilesForCommit", TRUE));
383 CString logmsg;
384 CAppUtils::Commit(GetSafeHwnd(),
385 L"",
386 m_bWholeProject,
387 logmsg,
388 pathList,
389 bSelectFilesForCommit);
391 OnBnClickedRefresh();
394 void CChangedDlg::OnBnClickedStash()
396 CIconMenu popup;
398 if (popup.CreatePopupMenu())
400 popup.AppendMenuIcon(ID_STASH_SAVE, IDS_MENUSTASHSAVE, IDI_SHELVE);
402 CTGitPath root = g_Git.m_CurrentDir;
403 if (root.HasStashDir())
405 popup.AppendMenuIcon(ID_STASH_POP, IDS_MENUSTASHPOP, IDI_UNSHELVE);
406 popup.AppendMenuIcon(ID_STASH_APPLY, IDS_MENUSTASHAPPLY, IDI_UNSHELVE);
407 popup.AppendMenuIcon(ID_STASH_LIST, IDS_MENUSTASHLIST, IDI_LOG);
410 RECT rect;
411 GetDlgItem(IDC_BUTTON_STASH)->GetWindowRect(&rect);
412 TPMPARAMS params;
413 params.cbSize = sizeof(TPMPARAMS);
414 params.rcExclude = rect;
415 int cmd = popup.TrackPopupMenuEx(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY | TPM_VERTICAL, rect.left, rect.top, this, &params);
417 switch (cmd & 0xFFFF)
419 case ID_STASH_SAVE:
420 CAppUtils::StashSave(GetSafeHwnd());
421 break;
422 case ID_STASH_POP:
423 CAppUtils::StashPop(GetSafeHwnd(), 2);
424 break;
425 case ID_STASH_APPLY:
426 CAppUtils::StashApply(GetSafeHwnd(), L"", false);
427 break;
428 case ID_STASH_LIST:
430 CRefLogDlg dlg;
431 dlg.m_CurrentBranch = L"refs/stash";
432 dlg.DoModal();
434 break;
435 default:
436 return;
438 OnBnClickedRefresh();
442 void CChangedDlg::OnBnClickedButtonUnifieddiff()
444 CTGitPath commonDirectory;
445 if (!m_bWholeProject)
446 commonDirectory = m_pathList.GetCommonRoot().GetDirectory();
447 bool bSingleFile = ((m_pathList.GetCount()==1)&&(!m_pathList[0].IsEmpty())&&(!m_pathList[0].IsDirectory()));
448 if (bSingleFile)
449 commonDirectory = m_pathList[0];
450 CString sCmd;
451 sCmd.Format(L"/command:showcompare /unified /path:\"%s\" /revision1:HEAD /revision2:%s", (LPCTSTR)g_Git.CombinePath(commonDirectory), (LPCTSTR)GitRev::GetWorkingCopy());
452 if (!!(GetAsyncKeyState(VK_SHIFT) & 0x8000))
453 sCmd += L" /alternative";
454 CAppUtils::RunTortoiseGitProc(sCmd);
457 void CChangedDlg::OnBnClickedWholeProject()
459 UpdateData();
460 m_regShowWholeProject = m_bWholeProject;
461 OnBnClickedRefresh();
464 void CChangedDlg::OnBnClickedShowStaged()
466 UpdateData();
467 m_regShowStaged = m_bShowStaged;
468 OnBnClickedRefresh();