Deduplicate code
[TortoiseGit.git] / src / TortoiseProc / ChangedDlg.cpp
blobe683399a13a213d86af98b7cbec2166cd3f2bf4e
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2014 - 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 "PathUtils.h"
27 #include "ChangedDlg.h"
28 #include "IconMenu.h"
29 #include "RefLogDlg.h"
31 #include "GitStatusListCtrl.h"
33 IMPLEMENT_DYNAMIC(CChangedDlg, CResizableStandAloneDialog)
34 CChangedDlg::CChangedDlg(CWnd* pParent /*=NULL*/)
35 : CResizableStandAloneDialog(CChangedDlg::IDD, pParent)
36 , m_bShowUnversioned(FALSE)
37 , m_iShowUnmodified(0)
38 , m_bBlock(FALSE)
39 , m_bCanceled(false)
40 , m_bShowIgnored(FALSE)
41 , m_bShowLocalChangesIgnored(FALSE)
42 , m_bWholeProject(FALSE)
44 m_bRemote = FALSE;
47 CChangedDlg::~CChangedDlg()
51 void CChangedDlg::DoDataExchange(CDataExchange* pDX)
53 CResizableStandAloneDialog::DoDataExchange(pDX);
54 DDX_Control(pDX, IDC_CHANGEDLIST, m_FileListCtrl);
55 DDX_Control(pDX, IDC_BUTTON_STASH, m_ctrlStash);
56 DDX_Check(pDX, IDC_SHOWUNVERSIONED, m_bShowUnversioned);
57 DDX_Check(pDX, IDC_SHOWUNMODIFIED, m_iShowUnmodified);
58 DDX_Check(pDX, IDC_SHOWIGNORED, m_bShowIgnored);
59 DDX_Check(pDX, IDC_SHOWLOCALCHANGESIGNORED, m_bShowLocalChangesIgnored);
60 DDX_Check(pDX, IDC_WHOLE_PROJECT, m_bWholeProject);
64 BEGIN_MESSAGE_MAP(CChangedDlg, CResizableStandAloneDialog)
65 ON_BN_CLICKED(IDC_SHOWUNVERSIONED, OnBnClickedShowunversioned)
66 ON_BN_CLICKED(IDC_SHOWUNMODIFIED, OnBnClickedShowUnmodified)
67 ON_REGISTERED_MESSAGE(CGitStatusListCtrl::GITSLNM_NEEDSREFRESH, OnSVNStatusListCtrlNeedsRefresh)
68 ON_REGISTERED_MESSAGE(CGitStatusListCtrl::GITSLNM_ITEMCOUNTCHANGED, OnSVNStatusListCtrlItemCountChanged)
69 ON_BN_CLICKED(IDC_SHOWIGNORED, &CChangedDlg::OnBnClickedShowignored)
70 ON_BN_CLICKED(IDC_REFRESH, &CChangedDlg::OnBnClickedRefresh)
71 ON_BN_CLICKED(IDC_COMMIT, &CChangedDlg::OnBnClickedCommit)
72 ON_BN_CLICKED(IDC_BUTTON_STASH, &CChangedDlg::OnBnClickedStash)
73 ON_BN_CLICKED(IDC_BUTTON_UNIFIEDDIFF, &CChangedDlg::OnBnClickedButtonUnifieddiff)
74 ON_BN_CLICKED(IDC_SHOWLOCALCHANGESIGNORED, &CChangedDlg::OnBnClickedShowlocalchangesignored)
75 ON_BN_CLICKED(IDC_WHOLE_PROJECT, OnBnClickedWholeProject)
76 END_MESSAGE_MAP()
78 BOOL CChangedDlg::OnInitDialog()
80 CResizableStandAloneDialog::OnInitDialog();
82 m_tooltips.Create(this);
84 m_regAddBeforeCommit = CRegDWORD(_T("Software\\TortoiseGit\\AddBeforeCommit"), TRUE);
85 m_bShowUnversioned = m_regAddBeforeCommit;
87 CString regPath(g_Git.m_CurrentDir);
88 regPath.Replace(_T(":"), _T("_"));
89 m_regShowWholeProject = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ShowWholeProject\\") + regPath, FALSE);
90 m_bWholeProject = m_regShowWholeProject;
91 SetDlgTitle();
93 UpdateData(FALSE);
95 m_FileListCtrl.Init(GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD| GITSLC_COLDEL | GITSLC_COLMODIFICATIONDATE, _T("ChangedDlg"),
96 (GITSLC_POPALL ^ (GITSLC_POPSAVEAS|GITSLC_POPRESTORE)), false);
97 m_FileListCtrl.SetCancelBool(&m_bCanceled);
98 m_FileListCtrl.SetBackgroundImage(IDI_CFM_BKG);
99 m_FileListCtrl.SetEmptyString(IDS_REPOSTATUS_EMPTYFILELIST);
101 AdjustControlSize(IDC_SHOWUNVERSIONED);
102 AdjustControlSize(IDC_SHOWUNMODIFIED);
103 AdjustControlSize(IDC_SHOWLOCALCHANGESIGNORED);
104 AdjustControlSize(IDC_SHOWIGNORED);
105 AdjustControlSize(IDC_WHOLE_PROJECT);
107 AddAnchor(IDC_CHANGEDLIST, TOP_LEFT, BOTTOM_RIGHT);
108 AddAnchor(IDC_SUMMARYTEXT, BOTTOM_LEFT, BOTTOM_RIGHT);
109 AddAnchor(IDC_SHOWUNVERSIONED, BOTTOM_LEFT);
110 AddAnchor(IDC_SHOWUNMODIFIED, BOTTOM_LEFT);
111 AddAnchor(IDC_SHOWLOCALCHANGESIGNORED, BOTTOM_LEFT);
112 AddAnchor(IDC_SHOWIGNORED, BOTTOM_LEFT);
113 AddAnchor(IDC_WHOLE_PROJECT, BOTTOM_LEFT);
114 AddAnchor(IDC_INFOLABEL, BOTTOM_RIGHT);
115 AddAnchor(IDC_BUTTON_STASH, BOTTOM_RIGHT);
116 AddAnchor(IDC_BUTTON_UNIFIEDDIFF, BOTTOM_RIGHT);
117 AddAnchor(IDC_COMMIT, BOTTOM_RIGHT);
118 AddAnchor(IDC_REFRESH, BOTTOM_RIGHT);
119 AddAnchor(IDOK, BOTTOM_RIGHT);
120 // SetPromptParentWindow(m_hWnd);
121 if (hWndExplorer)
122 CenterWindow(CWnd::FromHandle(hWndExplorer));
123 EnableSaveRestore(_T("ChangedDlg"));
125 m_bRemote = !!(DWORD)CRegDWORD(_T("Software\\TortoiseGit\\CheckRepo"), FALSE);
127 // first start a thread to obtain the status without
128 // blocking the dialog
129 if (AfxBeginThread(ChangedStatusThreadEntry, this)==NULL)
131 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
134 return TRUE;
137 UINT CChangedDlg::ChangedStatusThreadEntry(LPVOID pVoid)
139 return ((CChangedDlg*)pVoid)->ChangedStatusThread();
142 UINT CChangedDlg::ChangedStatusThread()
144 InterlockedExchange(&m_bBlock, TRUE);
146 g_Git.RefreshGitIndex();
148 m_bCanceled = false;
149 SetDlgItemText(IDOK, CString(MAKEINTRESOURCE(IDS_MSGBOX_CANCEL)));
150 DialogEnableWindow(IDC_REFRESH, FALSE);
151 DialogEnableWindow(IDC_SHOWUNVERSIONED, FALSE);
152 DialogEnableWindow(IDC_SHOWUNMODIFIED, FALSE);
153 DialogEnableWindow(IDC_SHOWIGNORED, FALSE);
154 DialogEnableWindow(IDC_SHOWLOCALCHANGESIGNORED, FALSE);
155 CString temp;
156 m_FileListCtrl.Clear();
157 if (!m_FileListCtrl.GetStatus(m_bWholeProject ? nullptr : &m_pathList, m_bRemote, m_bShowIgnored != FALSE, m_bShowUnversioned != FALSE, m_bShowLocalChangesIgnored != FALSE))
159 if (!m_FileListCtrl.GetLastErrorMessage().IsEmpty())
160 m_FileListCtrl.SetEmptyString(m_FileListCtrl.GetLastErrorMessage());
162 unsigned int dwShow = GITSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALS | GITSLC_SHOWLOCKS | GITSLC_SHOWSWITCHED | GITSLC_SHOWINCHANGELIST;
163 dwShow |= m_bShowUnversioned ? GITSLC_SHOWUNVERSIONED : 0;
164 dwShow |= m_iShowUnmodified ? GITSLC_SHOWNORMAL : 0;
165 dwShow |= m_bShowIgnored ? GITSLC_SHOWIGNORED : 0;
166 dwShow |= m_bShowLocalChangesIgnored ? GITSLC_SHOWASSUMEVALID | GITSLC_SHOWSKIPWORKTREE : 0;
167 m_FileListCtrl.Show(dwShow);
168 UpdateStatistics();
170 SetDlgTitle();
171 bool bIsDirectory = false;
172 if (m_pathList.GetCount() == 1)
173 bIsDirectory = m_pathList[0].IsDirectory() || m_pathList[0].IsEmpty(); // if it is empty it is g_Git.m_CurrentDir which is a directory
175 SetDlgItemText(IDOK, CString(MAKEINTRESOURCE(IDS_MSGBOX_OK)));
176 DialogEnableWindow(IDC_REFRESH, TRUE);
177 DialogEnableWindow(IDC_SHOWUNVERSIONED, bIsDirectory);
178 //DialogEnableWindow(IDC_SHOWUNMODIFIED, bIsDirectory);
179 DialogEnableWindow(IDC_SHOWIGNORED, bIsDirectory);
180 DialogEnableWindow(IDC_SHOWLOCALCHANGESIGNORED, TRUE);
181 InterlockedExchange(&m_bBlock, FALSE);
182 // revert the remote flag back to the default
183 m_bRemote = !!(DWORD)CRegDWORD(_T("Software\\TortoiseGit\\CheckRepo"), FALSE);
184 RefreshCursor();
185 return 0;
188 void CChangedDlg::OnOK()
190 if (m_bBlock)
192 m_bCanceled = true;
193 return;
195 __super::OnOK();
198 void CChangedDlg::OnCancel()
200 if (m_bBlock)
202 m_bCanceled = true;
203 return;
205 __super::OnCancel();
208 DWORD CChangedDlg::UpdateShowFlags()
210 DWORD dwShow = m_FileListCtrl.GetShowFlags();
211 if (m_bShowUnversioned)
212 dwShow |= GITSLC_SHOWUNVERSIONED;
213 else
214 dwShow &= ~GITSLC_SHOWUNVERSIONED;
215 if (m_iShowUnmodified)
216 dwShow |= GITSLC_SHOWNORMAL;
217 else
218 dwShow &= ~GITSLC_SHOWNORMAL;
219 if (m_bShowIgnored)
220 dwShow |= GITSLC_SHOWIGNORED;
221 else
222 dwShow &= ~GITSLC_SHOWIGNORED;
223 if (m_bShowLocalChangesIgnored)
224 dwShow |= GITSLC_SHOWASSUMEVALID|GITSLC_SHOWSKIPWORKTREE;
225 else
226 dwShow &= ~(GITSLC_SHOWASSUMEVALID|GITSLC_SHOWSKIPWORKTREE);
228 // old bShowExternals:
229 dwShow &= ~(GITSLC_SHOWEXTERNAL | GITSLC_SHOWINEXTERNALS | GITSLC_SHOWEXTERNALFROMDIFFERENTREPO);
231 return dwShow;
234 void CChangedDlg::SetDlgTitle()
236 if (m_sTitle.IsEmpty())
237 GetWindowText(m_sTitle);
239 if (m_bWholeProject)
240 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, m_sTitle);
241 else
243 if (m_pathList.GetCount() == 1)
244 CAppUtils::SetWindowTitle(m_hWnd, g_Git.CombinePath(m_pathList[0].GetUIPathString()), m_sTitle);
245 else
246 CAppUtils::SetWindowTitle(m_hWnd, g_Git.CombinePath(m_FileListCtrl.GetCommonDirectory(false)), m_sTitle);
250 void CChangedDlg::OnBnClickedShowunversioned()
252 UpdateData();
253 m_regAddBeforeCommit = m_bShowUnversioned;
254 if(m_FileListCtrl.m_FileLoaded & CGitStatusListCtrl::FILELIST_UNVER)
256 m_FileListCtrl.Show(UpdateShowFlags());
258 else
260 if(m_bShowUnversioned)
262 if (AfxBeginThread(ChangedStatusThreadEntry, this)==NULL)
264 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
268 UpdateStatistics();
271 void CChangedDlg::OnBnClickedShowUnmodified()
273 UpdateData();
274 m_FileListCtrl.Show(UpdateShowFlags());
275 m_regAddBeforeCommit = m_bShowUnversioned;
276 UpdateStatistics();
279 void CChangedDlg::OnBnClickedShowignored()
281 UpdateData();
282 if (m_FileListCtrl.m_FileLoaded & CGitStatusListCtrl::FILELIST_IGNORE)
283 m_FileListCtrl.Show(UpdateShowFlags());
284 else if (m_bShowIgnored)
286 if (AfxBeginThread(ChangedStatusThreadEntry, this) == nullptr)
287 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
289 UpdateStatistics();
292 void CChangedDlg::OnBnClickedShowlocalchangesignored()
294 UpdateData();
295 if (m_FileListCtrl.m_FileLoaded & CGitStatusListCtrl::FILELIST_LOCALCHANGESIGNORED)
296 m_FileListCtrl.Show(UpdateShowFlags());
297 else if (m_bShowLocalChangesIgnored)
299 if (AfxBeginThread(ChangedStatusThreadEntry, this) == nullptr)
300 CMessageBox::Show(nullptr, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
302 UpdateStatistics();
305 LRESULT CChangedDlg::OnSVNStatusListCtrlNeedsRefresh(WPARAM, LPARAM)
307 if (AfxBeginThread(ChangedStatusThreadEntry, this)==NULL)
309 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
311 return 0;
314 LRESULT CChangedDlg::OnSVNStatusListCtrlItemCountChanged(WPARAM, LPARAM)
316 UpdateStatistics();
317 return 0;
320 BOOL CChangedDlg::PreTranslateMessage(MSG* pMsg)
322 m_tooltips.RelayEvent(pMsg);
323 if (pMsg->message == WM_KEYDOWN)
325 switch (pMsg->wParam)
327 case VK_F5:
329 if (m_bBlock)
330 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
331 if (AfxBeginThread(ChangedStatusThreadEntry, this)==NULL)
333 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
336 break;
340 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
343 void CChangedDlg::OnBnClickedRefresh()
345 if (!m_bBlock)
347 if (AfxBeginThread(ChangedStatusThreadEntry, this)==NULL)
349 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
354 void CChangedDlg::UpdateStatistics()
356 CString temp;
357 #if 0
358 LONG lMin, lMax;
360 m_FileListCtrl.GetMinMaxRevisions(lMin, lMax, true, false);
361 if (LONG(m_FileListCtrl.m_HeadRev) >= 0)
363 temp.Format(IDS_REPOSTATUS_HEADREV, lMin, lMax, LONG(m_FileListCtrl.m_HeadRev));
364 SetDlgItemText(IDC_SUMMARYTEXT, temp);
366 else
368 temp.Format(IDS_REPOSTATUS_WCINFO, lMin, lMax);
369 SetDlgItemText(IDC_SUMMARYTEXT, temp);
371 #endif
372 temp = m_FileListCtrl.GetStatisticsString();
373 temp.Replace(_T(" = "), _T("="));
374 temp.Replace(_T("\n"), _T(", "));
375 SetDlgItemText(IDC_INFOLABEL, temp);
379 void CChangedDlg::OnBnClickedCommit()
381 CString cmd = _T("/command:commit /path:\"");
382 bool bSingleFile = ((m_pathList.GetCount()==1)&&(!m_pathList[0].IsEmpty())&&(!m_pathList[0].IsDirectory()));
383 if (bSingleFile)
384 cmd += m_pathList[0].GetWinPathString();
385 else
386 cmd += g_Git.CombinePath(m_pathList.GetCommonRoot().GetDirectory());
387 cmd += _T("\"");
388 CAppUtils::RunTortoiseGitProc(cmd);
391 void CChangedDlg::OnBnClickedStash()
393 CIconMenu popup;
395 if (popup.CreatePopupMenu())
397 popup.AppendMenuIcon(ID_STASH_SAVE, IDS_MENUSTASHSAVE, IDI_COMMIT);
399 CTGitPath root = g_Git.m_CurrentDir;
400 if (root.HasStashDir())
402 popup.AppendMenuIcon(ID_STASH_POP, IDS_MENUSTASHPOP, IDI_RELOCATE);
403 popup.AppendMenuIcon(ID_STASH_APPLY, IDS_MENUSTASHAPPLY, IDI_RELOCATE);
404 popup.AppendMenuIcon(ID_STASH_LIST, IDS_MENUSTASHLIST, IDI_LOG);
407 POINT cursorPos;
408 GetCursorPos(&cursorPos);
409 int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, cursorPos.x, cursorPos.y, this, 0);
411 switch (cmd & 0xFFFF)
413 case ID_STASH_SAVE:
414 CAppUtils::StashSave();
415 break;
416 case ID_STASH_POP:
417 CAppUtils::StashPop(false);
418 break;
419 case ID_STASH_APPLY:
420 CAppUtils::StashApply(_T(""), false);
421 break;
422 case ID_STASH_LIST:
424 CRefLogDlg dlg;
425 dlg.m_CurrentBranch = _T("refs/stash");
426 dlg.DoModal();
428 break;
429 default:
430 return;
432 OnBnClickedRefresh();
436 void CChangedDlg::OnBnClickedButtonUnifieddiff()
438 CTGitPath commonDirectory = m_bWholeProject ? g_Git.m_CurrentDir : m_pathList.GetCommonRoot().GetDirectory();
439 bool bSingleFile = ((m_pathList.GetCount()==1)&&(!m_pathList[0].IsEmpty())&&(!m_pathList[0].IsDirectory()));
440 if (bSingleFile)
441 commonDirectory = m_pathList[0];
442 CAppUtils::StartShowUnifiedDiff(m_hWnd, commonDirectory, GitRev::GetHead(), commonDirectory, GitRev::GetWorkingCopy());
445 void CChangedDlg::OnBnClickedWholeProject()
447 UpdateData();
448 m_regShowWholeProject = m_bWholeProject;
449 OnBnClickedRefresh();