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.
21 #include "TortoiseProc.h"
22 #include "ChangedDlg.h"
23 #include "MessageBox.h"
26 #include "ChangedDlg.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)
37 , m_bShowIgnored(FALSE
)
38 , m_bShowLocalChangesIgnored(FALSE
)
39 , m_bWholeProject(FALSE
)
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
)
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
;
93 if (m_pathList
.GetCount() == 1 && m_pathList
[0].GetWinPathString().IsEmpty())
95 m_bWholeProject
= BST_CHECKED
;
96 DialogEnableWindow(IDC_WHOLE_PROJECT
, 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
);
146 UINT
CChangedDlg::ChangedStatusThreadEntry(LPVOID pVoid
)
148 return reinterpret_cast<CChangedDlg
*>(pVoid
)->ChangedStatusThread();
151 UINT
CChangedDlg::ChangedStatusThread()
153 InterlockedExchange(&m_bBlock
, TRUE
);
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
);
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
);
201 void CChangedDlg::OnOK()
211 void CChangedDlg::OnCancel()
221 DWORD
CChangedDlg::UpdateShowFlags()
223 DWORD dwShow
= m_FileListCtrl
.GetShowFlags();
224 if (m_bShowUnversioned
)
225 dwShow
|= GITSLC_SHOWUNVERSIONED
;
227 dwShow
&= ~GITSLC_SHOWUNVERSIONED
;
228 if (m_iShowUnmodified
)
229 dwShow
|= GITSLC_SHOWNORMAL
;
231 dwShow
&= ~GITSLC_SHOWNORMAL
;
233 dwShow
|= GITSLC_SHOWIGNORED
;
235 dwShow
&= ~GITSLC_SHOWIGNORED
;
236 if (m_bShowLocalChangesIgnored
)
237 dwShow
|= GITSLC_SHOWASSUMEVALID
|GITSLC_SHOWSKIPWORKTREE
;
239 dwShow
&= ~(GITSLC_SHOWASSUMEVALID
|GITSLC_SHOWSKIPWORKTREE
);
241 // old bShowExternals:
242 dwShow
&= ~(GITSLC_SHOWEXTERNAL
| GITSLC_SHOWINEXTERNALS
| GITSLC_SHOWEXTERNALFROMDIFFERENTREPO
);
247 void CChangedDlg::SetDlgTitle()
249 if (m_sTitle
.IsEmpty())
250 GetWindowText(m_sTitle
);
253 CAppUtils::SetWindowTitle(m_hWnd
, g_Git
.m_CurrentDir
, m_sTitle
);
256 if (m_pathList
.GetCount() == 1)
257 CAppUtils::SetWindowTitle(m_hWnd
, g_Git
.CombinePath(m_pathList
[0].GetUIPathString()), m_sTitle
);
259 CAppUtils::SetWindowTitle(m_hWnd
, g_Git
.CombinePath(m_FileListCtrl
.GetCommonDirectory(false)), m_sTitle
);
263 void CChangedDlg::OnBnClickedShowunversioned()
266 m_regAddBeforeCommit
= m_bShowUnversioned
;
267 if(m_FileListCtrl
.m_FileLoaded
& CGitStatusListCtrl::FILELIST_UNVER
)
269 m_FileListCtrl
.StoreScrollPos();
270 m_FileListCtrl
.Show(UpdateShowFlags());
274 if(m_bShowUnversioned
)
276 if (!AfxBeginThread(ChangedStatusThreadEntry
, this))
277 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
283 void CChangedDlg::OnBnClickedShowUnmodified()
286 m_FileListCtrl
.StoreScrollPos();
287 m_FileListCtrl
.Show(UpdateShowFlags());
288 m_regAddBeforeCommit
= m_bShowUnversioned
;
292 void CChangedDlg::OnBnClickedShowignored()
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
);
306 void CChangedDlg::OnBnClickedShowlocalchangesignored()
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
);
320 LRESULT
CChangedDlg::OnSVNStatusListCtrlNeedsRefresh(WPARAM
, LPARAM
)
322 if (!AfxBeginThread(ChangedStatusThreadEntry
, this))
323 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
327 LRESULT
CChangedDlg::OnSVNStatusListCtrlItemCountChanged(WPARAM
, LPARAM
)
333 BOOL
CChangedDlg::PreTranslateMessage(MSG
* pMsg
)
335 if (pMsg
->message
== WM_KEYDOWN
)
337 switch (pMsg
->wParam
)
342 return CResizableStandAloneDialog::PreTranslateMessage(pMsg
);
343 if (!AfxBeginThread(ChangedStatusThreadEntry
, this))
345 CMessageBox::Show(GetSafeHwnd(), IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
352 return CResizableStandAloneDialog::PreTranslateMessage(pMsg
);
355 void CChangedDlg::OnBnClickedRefresh()
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());
377 pathList
.AddPath(m_pathList
[0]);
379 pathList
.AddPath(m_pathList
.GetCommonRoot().GetDirectory());
381 bool bSelectFilesForCommit
= !!DWORD(CRegStdDWORD(L
"Software\\TortoiseGit\\SelectFilesForCommit", TRUE
));
384 CAppUtils::Commit(GetSafeHwnd(),
389 bSelectFilesForCommit
);
391 OnBnClickedRefresh();
394 void CChangedDlg::OnBnClickedStash()
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
);
411 GetDlgItem(IDC_BUTTON_STASH
)->GetWindowRect(&rect
);
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, ¶ms
);
417 switch (cmd
& 0xFFFF)
420 CAppUtils::StashSave(GetSafeHwnd());
423 CAppUtils::StashPop(GetSafeHwnd(), 2);
426 CAppUtils::StashApply(GetSafeHwnd(), L
"", false);
431 dlg
.m_CurrentBranch
= L
"refs/stash";
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()));
449 commonDirectory
= m_pathList
[0];
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()
460 m_regShowWholeProject
= m_bWholeProject
;
461 OnBnClickedRefresh();
464 void CChangedDlg::OnBnClickedShowStaged()
467 m_regShowStaged
= m_bShowStaged
;
468 OnBnClickedRefresh();