Fix warnings
[TortoiseGit.git] / src / TortoiseProc / SubmoduleUpdateDlg.cpp
blob752aaaa3fd9b5c93828a99cefe082803b1038001
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2017, 2019, 2022 - 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.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "SubmoduleUpdateDlg.h"
23 #include "AppUtils.h"
24 #include "UnicodeUtils.h"
26 IMPLEMENT_DYNAMIC(CSubmoduleUpdateDlg, CResizableStandAloneDialog)
28 bool CSubmoduleUpdateDlg::s_bSortLogical = true;
30 CSubmoduleUpdateDlg::CSubmoduleUpdateDlg(CWnd* pParent /*=nullptr*/)
31 : CResizableStandAloneDialog(CSubmoduleUpdateDlg::IDD, pParent)
32 , m_bInit(TRUE)
33 , m_bRecursive(FALSE)
34 , m_bForce(FALSE)
35 , m_bNoFetch(FALSE)
36 , m_bMerge(FALSE)
37 , m_bRebase(FALSE)
38 , m_bRemote(FALSE)
39 , m_bWholeProject(FALSE)
40 , m_bAllSubmodulesSelected(false)
42 s_bSortLogical = !CRegDWORD(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_CURRENT_USER);
43 if (s_bSortLogical)
44 s_bSortLogical = !CRegDWORD(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_LOCAL_MACHINE);
47 CSubmoduleUpdateDlg::~CSubmoduleUpdateDlg()
51 void CSubmoduleUpdateDlg::DoDataExchange(CDataExchange* pDX)
53 CResizableStandAloneDialog::DoDataExchange(pDX);
54 DDX_Control(pDX, IDC_LIST_PATH, m_PathListBox);
55 DDX_Control(pDX, IDC_SELECTALL, m_SelectAll);
56 DDX_Check(pDX, IDC_WHOLE_PROJECT, m_bWholeProject);
57 DDX_Check(pDX, IDC_CHECK_SUBMODULE_INIT, m_bInit);
58 DDX_Check(pDX, IDC_CHECK_SUBMODULE_RECURSIVE, m_bRecursive);
59 DDX_Check(pDX, IDC_FORCE, m_bForce);
60 DDX_Check(pDX, IDC_CHECK_SUBMODULE_NOFETCH, m_bNoFetch);
61 DDX_Check(pDX, IDC_CHECK_SUBMODULE_MERGE, m_bMerge);
62 DDX_Check(pDX, IDC_CHECK_SUBMODULE_REBASE, m_bRebase);
63 DDX_Check(pDX, IDC_CHECK_SUBMODULE_REMOTE, m_bRemote);
66 BEGIN_MESSAGE_MAP(CSubmoduleUpdateDlg, CResizableStandAloneDialog)
67 ON_BN_CLICKED(IDC_SELECTALL, OnBnClickedSelectall)
68 ON_BN_CLICKED(IDC_WHOLE_PROJECT, OnBnClickedShowWholeProject)
69 ON_BN_CLICKED(IDOK, &CSubmoduleUpdateDlg::OnBnClickedOk)
70 ON_LBN_SELCHANGE(IDC_LIST_PATH, &CSubmoduleUpdateDlg::OnLbnSelchangeListPath)
71 END_MESSAGE_MAP()
73 static int SubmoduleCallback(git_submodule *sm, const char * /*name*/, void *payload)
75 auto list = *static_cast<STRING_VECTOR**>(payload);
76 auto prefixList = *(static_cast<STRING_VECTOR**>(payload) + 1);
77 CString path = CUnicodeUtils::GetUnicode(git_submodule_path(sm));
78 if (prefixList->empty())
79 list->push_back(path);
80 else
82 for (size_t i = 0; i < prefixList->size(); ++i)
84 CString prefix = prefixList->at(i) + L'/';
85 if (CStringUtils::StartsWith(path, prefix))
86 list->push_back(path);
89 return 0;
92 int LogicalComparePredicate(const CString &left, const CString &right)
94 if (CSubmoduleUpdateDlg::s_bSortLogical)
95 return StrCmpLogicalW(left, right) < 0;
96 return StrCmpI(left, right) < 0;
99 static void GetSubmodulePathList(STRING_VECTOR &list, STRING_VECTOR &prefixList)
101 CAutoRepository repo(g_Git.GetGitRepository());
102 if (!repo)
104 MessageBox(nullptr, CGit::GetLibGit2LastErr(L"Could not open repository."), L"TortoiseGit", MB_ICONERROR);
105 return;
108 STRING_VECTOR *listParams[] = { &list, &prefixList };
109 if (git_submodule_foreach(repo, SubmoduleCallback, &listParams))
111 MessageBox(nullptr, CGit::GetLibGit2LastErr(L"Could not get submodule list."), L"TortoiseGit", MB_ICONERROR);
112 return;
115 std::sort(list.begin(), list.end(), LogicalComparePredicate);
118 BOOL CSubmoduleUpdateDlg::OnInitDialog()
120 CResizableStandAloneDialog::OnInitDialog();
121 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
123 AdjustControlSize(IDC_CHECK_SUBMODULE_INIT);
124 AdjustControlSize(IDC_CHECK_SUBMODULE_RECURSIVE);
125 AdjustControlSize(IDC_CHECK_SUBMODULE_NOFETCH);
126 AdjustControlSize(IDC_CHECK_SUBMODULE_MERGE);
127 AdjustControlSize(IDC_CHECK_SUBMODULE_REBASE);
129 AddAnchor(IDOK, BOTTOM_RIGHT);
130 AddAnchor(IDCANCEL, BOTTOM_RIGHT);
131 AddAnchor(IDHELP, BOTTOM_RIGHT);
132 AddAnchor(static_cast<UINT>(IDC_STATIC), TOP_LEFT);
133 AddAnchor(IDC_LIST_PATH, TOP_LEFT, BOTTOM_RIGHT);
134 AddAnchor(IDC_SELECTALL, BOTTOM_LEFT);
135 AddAnchor(IDC_WHOLE_PROJECT, BOTTOM_LEFT);
136 AddAnchor(IDC_GROUP_INFO, BOTTOM_LEFT, BOTTOM_RIGHT);
137 AddAnchor(IDC_CHECK_SUBMODULE_INIT, BOTTOM_LEFT);
138 AddAnchor(IDC_CHECK_SUBMODULE_RECURSIVE, BOTTOM_LEFT);
139 AddAnchor(IDC_FORCE, BOTTOM_LEFT);
140 AddAnchor(IDC_CHECK_SUBMODULE_REMOTE, BOTTOM_LEFT);
141 AddAnchor(IDC_CHECK_SUBMODULE_NOFETCH, BOTTOM_RIGHT);
142 AddAnchor(IDC_CHECK_SUBMODULE_MERGE, BOTTOM_RIGHT);
143 AddAnchor(IDC_CHECK_SUBMODULE_REBASE, BOTTOM_RIGHT);
145 CString str(g_Git.m_CurrentDir);
146 str.Replace(L':', L'_');
147 m_regShowWholeProject = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\ShowWholeProject\\" + str, FALSE);
148 m_bWholeProject = m_regShowWholeProject;
150 m_regInit = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\init", TRUE);
151 m_bInit = m_regInit;
152 m_regRecursive = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\recursive", FALSE);
153 m_bRecursive = m_regRecursive;
154 m_regForce = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\force", FALSE);
155 m_bForce = m_regForce;
156 m_regRemote = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\remote", FALSE);
157 m_bRemote = m_regRemote;
158 m_regNoFetch = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\nofetch", FALSE);
159 m_bNoFetch = m_regNoFetch;
160 m_regMerge = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\merge", FALSE);
161 m_bMerge = m_regMerge;
162 m_regRebase = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\rebase", FALSE);
163 m_bRebase = m_regRebase;
165 DialogEnableWindow(IDC_WHOLE_PROJECT, !(m_PathFilterList.empty() || (m_PathFilterList.size() == 1 && m_PathFilterList[0].IsEmpty())));
167 SetDlgTitle();
169 EnableSaveRestore(L"SubmoduleUpdateDlg");
171 Refresh();
172 UpdateData(FALSE);
174 return TRUE;
177 void CSubmoduleUpdateDlg::SetDlgTitle()
179 if (m_sTitle.IsEmpty())
180 GetWindowText(m_sTitle);
181 CString dir = g_Git.m_CurrentDir;
182 if (!m_bWholeProject)
184 if (!m_PathFilterList.empty())
185 dir += (CStringUtils::EndsWith(g_Git.m_CurrentDir, L'\\') ? L"" : L"\\") + CTGitPath(m_PathFilterList[0]).GetWinPathString();
186 if (m_PathFilterList.size() > 1)
187 dir += L", ...";
189 CAppUtils::SetWindowTitle(m_hWnd, dir, m_sTitle);
192 void CSubmoduleUpdateDlg::OnBnClickedOk()
194 CResizableStandAloneDialog::UpdateData(TRUE);
195 m_PathList.clear();
197 CString selected;
198 for (int i = 0; i < m_PathListBox.GetCount(); ++i)
200 if (m_PathListBox.GetSel(i))
202 if (!selected.IsEmpty())
203 selected.AppendChar(L'|');
204 CString text;
205 m_PathListBox.GetText(i, text);
206 m_PathList.push_back(text);
207 selected.Append(text);
210 m_bAllSubmodulesSelected = (static_cast<size_t>(m_PathListBox.GetCount()) == m_PathList.size());
211 m_regPath = selected;
213 m_regInit = m_bInit;
214 m_regRecursive = m_bRecursive;
215 m_regForce = m_bForce;
216 m_regRemote = m_bRemote;
217 m_regNoFetch = m_bNoFetch;
218 m_regMerge = m_bMerge;
219 m_regRebase = m_bRebase;
221 CResizableStandAloneDialog::OnOK();
224 void CSubmoduleUpdateDlg::OnLbnSelchangeListPath()
226 GetDlgItem(IDOK)->EnableWindow(m_PathListBox.GetSelCount() > 0 ? TRUE : FALSE);
227 if (m_PathListBox.GetSelCount() == 0)
228 m_SelectAll.SetCheck(BST_UNCHECKED);
229 else if (m_PathListBox.GetSelCount() < m_PathListBox.GetCount())
230 m_SelectAll.SetCheck(BST_INDETERMINATE);
231 else
232 m_SelectAll.SetCheck(BST_CHECKED);
235 void CSubmoduleUpdateDlg::OnBnClickedSelectall()
237 UINT state = (m_SelectAll.GetState() & 0x0003);
238 if (state == BST_INDETERMINATE)
240 // It is not at all useful to manually place the checkbox into the indeterminate state...
241 // We will force this on to the unchecked state
242 state = BST_UNCHECKED;
243 m_SelectAll.SetCheck(state);
245 if (state == BST_UNCHECKED)
247 for (int i = 0; i < m_PathListBox.GetCount(); ++i)
248 m_PathListBox.SetSel(i, FALSE);
250 else
252 for (int i = 0; i < m_PathListBox.GetCount(); ++i)
253 m_PathListBox.SetSel(i, TRUE);
255 OnLbnSelchangeListPath();
258 void CSubmoduleUpdateDlg::OnBnClickedShowWholeProject()
260 UpdateData();
261 m_regShowWholeProject = m_bWholeProject;
262 SetDlgTitle();
263 Refresh();
266 void CSubmoduleUpdateDlg::Refresh()
268 while (m_PathListBox.GetCount() > 0)
269 m_PathListBox.DeleteString(m_PathListBox.GetCount() - 1);
271 CString WorkingDir = g_Git.m_CurrentDir;
272 WorkingDir.Replace(L':', L'_');
274 m_regPath = CRegString(L"Software\\TortoiseGit\\History\\SubmoduleUpdatePath\\" + WorkingDir);
275 CString path = m_regPath;
276 STRING_VECTOR emptylist;
277 STRING_VECTOR list;
278 GetSubmodulePathList(list, m_bWholeProject ? emptylist : m_PathFilterList);
279 STRING_VECTOR selected;
280 if (m_PathList.empty())
282 int pos = 0;
283 while (pos >= 0)
285 CString part = path.Tokenize(L"|", pos);
286 if (!part.IsEmpty())
287 selected.push_back(part);
290 else
292 for (size_t i = 0; i < m_PathList.size(); ++i)
293 selected.push_back(m_PathList[i]);
296 for (size_t i = 0; i < list.size(); ++i)
298 m_PathListBox.AddString(list[i]);
299 if (selected.size() == 0)
300 m_PathListBox.SetSel(static_cast<int>(i));
301 else
303 for (size_t j = 0; j < selected.size(); ++j)
305 if (selected[j] == list[i])
306 m_PathListBox.SetSel(static_cast<int>(i));
311 OnLbnSelchangeListPath();