PageRenderTime 105ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/TortoiseProc/SubmoduleUpdateDlg.cpp

https://gitlab.com/Sajjad-dehghani/tortoisegit
C++ | 311 lines | 269 code | 28 blank | 14 comment | 24 complexity | c94572f7dcae83baee289e4aceebfb70 MD5 | raw file
  1. // TortoiseGit - a Windows shell extension for easy version control
  2. // Copyright (C) 2012-2016 - TortoiseGit
  3. // This program is free software; you can redistribute it and/or
  4. // modify it under the terms of the GNU General Public License
  5. // as published by the Free Software Foundation; either version 2
  6. // of the License, or (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program; if not, write to the Free Software Foundation,
  13. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  14. //
  15. #include "stdafx.h"
  16. #include "TortoiseProc.h"
  17. #include "SubmoduleUpdateDlg.h"
  18. #include "AppUtils.h"
  19. #include "UnicodeUtils.h"
  20. #include "MessageBox.h"
  21. IMPLEMENT_DYNAMIC(CSubmoduleUpdateDlg, CResizableStandAloneDialog)
  22. bool CSubmoduleUpdateDlg::s_bSortLogical = true;
  23. CSubmoduleUpdateDlg::CSubmoduleUpdateDlg(CWnd* pParent /*=nullptr*/)
  24. : CResizableStandAloneDialog(CSubmoduleUpdateDlg::IDD, pParent)
  25. , m_bInit(TRUE)
  26. , m_bRecursive(FALSE)
  27. , m_bForce(FALSE)
  28. , m_bNoFetch(FALSE)
  29. , m_bMerge(FALSE)
  30. , m_bRebase(FALSE)
  31. , m_bRemote(FALSE)
  32. , m_bWholeProject(FALSE)
  33. {
  34. s_bSortLogical = !CRegDWORD(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_CURRENT_USER);
  35. if (s_bSortLogical)
  36. s_bSortLogical = !CRegDWORD(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_LOCAL_MACHINE);
  37. }
  38. CSubmoduleUpdateDlg::~CSubmoduleUpdateDlg()
  39. {
  40. }
  41. void CSubmoduleUpdateDlg::DoDataExchange(CDataExchange* pDX)
  42. {
  43. CResizableStandAloneDialog::DoDataExchange(pDX);
  44. DDX_Control(pDX, IDC_LIST_PATH, m_PathListBox);
  45. DDX_Control(pDX, IDC_SELECTALL, m_SelectAll);
  46. DDX_Check(pDX, IDC_WHOLE_PROJECT, m_bWholeProject);
  47. DDX_Check(pDX, IDC_CHECK_SUBMODULE_INIT, m_bInit);
  48. DDX_Check(pDX, IDC_CHECK_SUBMODULE_RECURSIVE, m_bRecursive);
  49. DDX_Check(pDX, IDC_FORCE, m_bForce);
  50. DDX_Check(pDX, IDC_CHECK_SUBMODULE_NOFETCH, m_bNoFetch);
  51. DDX_Check(pDX, IDC_CHECK_SUBMODULE_MERGE, m_bMerge);
  52. DDX_Check(pDX, IDC_CHECK_SUBMODULE_REBASE, m_bRebase);
  53. DDX_Check(pDX, IDC_CHECK_SUBMODULE_REMOTE, m_bRemote);
  54. }
  55. BEGIN_MESSAGE_MAP(CSubmoduleUpdateDlg, CResizableStandAloneDialog)
  56. ON_BN_CLICKED(IDC_SELECTALL, OnBnClickedSelectall)
  57. ON_BN_CLICKED(IDC_WHOLE_PROJECT, OnBnClickedShowWholeProject)
  58. ON_BN_CLICKED(IDOK, &CSubmoduleUpdateDlg::OnBnClickedOk)
  59. ON_LBN_SELCHANGE(IDC_LIST_PATH, &CSubmoduleUpdateDlg::OnLbnSelchangeListPath)
  60. END_MESSAGE_MAP()
  61. static int SubmoduleCallback(git_submodule *sm, const char * /*name*/, void *payload)
  62. {
  63. STRING_VECTOR *list = *(STRING_VECTOR **)payload;
  64. STRING_VECTOR *prefixList = *((STRING_VECTOR **)payload + 1);
  65. CString path = CUnicodeUtils::GetUnicode(git_submodule_path(sm));
  66. if (prefixList->empty())
  67. list->push_back(path);
  68. else
  69. {
  70. for (size_t i = 0; i < prefixList->size(); ++i)
  71. {
  72. CString prefix = prefixList->at(i) + _T("/");
  73. if (CStringUtils::StartsWith(path, prefix))
  74. list->push_back(path);
  75. }
  76. }
  77. return 0;
  78. }
  79. int LogicalComparePredicate(const CString &left, const CString &right)
  80. {
  81. if (CSubmoduleUpdateDlg::s_bSortLogical)
  82. return StrCmpLogicalW(left, right) < 0;
  83. return StrCmpI(left, right) < 0;
  84. }
  85. static void GetSubmodulePathList(STRING_VECTOR &list, STRING_VECTOR &prefixList)
  86. {
  87. CAutoRepository repo(g_Git.GetGitRepository());
  88. if (!repo)
  89. {
  90. MessageBox(nullptr, CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR);
  91. return;
  92. }
  93. STRING_VECTOR *listParams[] = { &list, &prefixList };
  94. if (git_submodule_foreach(repo, SubmoduleCallback, &listParams))
  95. {
  96. MessageBox(nullptr, CGit::GetLibGit2LastErr(_T("Could not get submodule list.")), _T("TortoiseGit"), MB_ICONERROR);
  97. return;
  98. }
  99. std::sort(list.begin(), list.end(), LogicalComparePredicate);
  100. }
  101. BOOL CSubmoduleUpdateDlg::OnInitDialog()
  102. {
  103. CResizableStandAloneDialog::OnInitDialog();
  104. CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
  105. AddAnchor(IDOK, BOTTOM_RIGHT);
  106. AddAnchor(IDCANCEL, BOTTOM_RIGHT);
  107. AddAnchor(IDHELP, BOTTOM_RIGHT);
  108. AddAnchor((UINT)IDC_STATIC, TOP_LEFT);
  109. AddAnchor(IDC_LIST_PATH, TOP_LEFT, BOTTOM_RIGHT);
  110. AddAnchor(IDC_SELECTALL, BOTTOM_LEFT);
  111. AddAnchor(IDC_WHOLE_PROJECT, BOTTOM_LEFT);
  112. AddAnchor(IDC_GROUP_INFO, BOTTOM_LEFT, BOTTOM_RIGHT);
  113. AddAnchor(IDC_CHECK_SUBMODULE_INIT, BOTTOM_LEFT);
  114. AddAnchor(IDC_CHECK_SUBMODULE_RECURSIVE, BOTTOM_LEFT);
  115. AddAnchor(IDC_FORCE, BOTTOM_LEFT);
  116. AddAnchor(IDC_CHECK_SUBMODULE_REMOTE, BOTTOM_LEFT);
  117. AddAnchor(IDC_CHECK_SUBMODULE_NOFETCH, BOTTOM_RIGHT);
  118. AddAnchor(IDC_CHECK_SUBMODULE_MERGE, BOTTOM_RIGHT);
  119. AddAnchor(IDC_CHECK_SUBMODULE_REBASE, BOTTOM_RIGHT);
  120. CString str(g_Git.m_CurrentDir);
  121. str.Replace(_T(":"), _T("_"));
  122. m_regShowWholeProject = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ShowWholeProject\\") + str, FALSE);
  123. m_bWholeProject = m_regShowWholeProject;
  124. m_regInit = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\") + str + _T("\\init"), TRUE);
  125. m_bInit = m_regInit;
  126. m_regRecursive = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\") + str + _T("\\recursive"), FALSE);
  127. m_bRecursive = m_regRecursive;
  128. m_regForce = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\") + str + _T("\\force"), FALSE);
  129. m_bForce = m_regForce;
  130. m_regRemote = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\") + str + _T("\\remote"), FALSE);
  131. m_bRemote = m_regRemote;
  132. m_regNoFetch = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\") + str + _T("\\nofetch"), FALSE);
  133. m_bNoFetch = m_regNoFetch;
  134. m_regMerge = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\") + str + _T("\\merge"), FALSE);
  135. m_bMerge = m_regMerge;
  136. m_regRebase = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\") + str + _T("\\rebase"), FALSE);
  137. m_bRebase = m_regRebase;
  138. DialogEnableWindow(IDC_WHOLE_PROJECT, !(m_PathFilterList.empty() || (m_PathFilterList.size() == 1 && m_PathFilterList[0].IsEmpty())));
  139. SetDlgTitle();
  140. AdjustControlSize(IDC_CHECK_SUBMODULE_INIT);
  141. AdjustControlSize(IDC_CHECK_SUBMODULE_RECURSIVE);
  142. AdjustControlSize(IDC_CHECK_SUBMODULE_NOFETCH);
  143. AdjustControlSize(IDC_CHECK_SUBMODULE_MERGE);
  144. AdjustControlSize(IDC_CHECK_SUBMODULE_REBASE);
  145. EnableSaveRestore(_T("SubmoduleUpdateDlg"));
  146. Refresh();
  147. UpdateData(FALSE);
  148. return TRUE;
  149. }
  150. void CSubmoduleUpdateDlg::SetDlgTitle()
  151. {
  152. if (m_sTitle.IsEmpty())
  153. GetWindowText(m_sTitle);
  154. CString dir = g_Git.m_CurrentDir;
  155. if (!m_bWholeProject)
  156. {
  157. if (!m_PathFilterList.empty())
  158. dir += (g_Git.m_CurrentDir.Right(1) == _T('\\') ? _T("") : _T("\\")) + CTGitPath(m_PathFilterList[0]).GetWinPathString();
  159. if (m_PathFilterList.size() > 1)
  160. dir += _T(", ...");
  161. }
  162. CAppUtils::SetWindowTitle(m_hWnd, dir, m_sTitle);
  163. }
  164. void CSubmoduleUpdateDlg::OnBnClickedOk()
  165. {
  166. CResizableStandAloneDialog::UpdateData(TRUE);
  167. m_PathList.clear();
  168. CString selected;
  169. for (int i = 0; i < m_PathListBox.GetCount(); ++i)
  170. {
  171. if (m_PathListBox.GetSel(i))
  172. {
  173. if (!selected.IsEmpty())
  174. selected.Append(_T("|"));
  175. CString text;
  176. m_PathListBox.GetText(i, text);
  177. m_PathList.push_back(text);
  178. selected.Append(text);
  179. }
  180. }
  181. m_regPath = selected;
  182. m_regInit = m_bInit;
  183. m_regRecursive = m_bRecursive;
  184. m_regForce = m_bForce;
  185. m_regRemote = m_bRemote;
  186. m_regNoFetch = m_bNoFetch;
  187. m_regMerge = m_bMerge;
  188. m_regRebase = m_bRebase;
  189. CResizableStandAloneDialog::OnOK();
  190. }
  191. void CSubmoduleUpdateDlg::OnLbnSelchangeListPath()
  192. {
  193. GetDlgItem(IDOK)->EnableWindow(m_PathListBox.GetSelCount() > 0 ? TRUE : FALSE);
  194. if (m_PathListBox.GetSelCount() == 0)
  195. m_SelectAll.SetCheck(BST_UNCHECKED);
  196. else if ((int)m_PathListBox.GetSelCount() < m_PathListBox.GetCount())
  197. m_SelectAll.SetCheck(BST_INDETERMINATE);
  198. else
  199. m_SelectAll.SetCheck(BST_CHECKED);
  200. }
  201. void CSubmoduleUpdateDlg::OnBnClickedSelectall()
  202. {
  203. UINT state = (m_SelectAll.GetState() & 0x0003);
  204. if (state == BST_INDETERMINATE)
  205. {
  206. // It is not at all useful to manually place the checkbox into the indeterminate state...
  207. // We will force this on to the unchecked state
  208. state = BST_UNCHECKED;
  209. m_SelectAll.SetCheck(state);
  210. }
  211. if (state == BST_UNCHECKED)
  212. {
  213. for (int i = 0; i < m_PathListBox.GetCount(); ++i)
  214. m_PathListBox.SetSel(i, FALSE);
  215. }
  216. else
  217. {
  218. for (int i = 0; i < m_PathListBox.GetCount(); ++i)
  219. m_PathListBox.SetSel(i, TRUE);
  220. }
  221. OnLbnSelchangeListPath();
  222. }
  223. void CSubmoduleUpdateDlg::OnBnClickedShowWholeProject()
  224. {
  225. UpdateData();
  226. m_regShowWholeProject = m_bWholeProject;
  227. SetDlgTitle();
  228. Refresh();
  229. }
  230. void CSubmoduleUpdateDlg::Refresh()
  231. {
  232. while (m_PathListBox.GetCount() > 0)
  233. m_PathListBox.DeleteString(m_PathListBox.GetCount() - 1);
  234. CString WorkingDir = g_Git.m_CurrentDir;
  235. WorkingDir.Replace(_T(':'), _T('_'));
  236. m_regPath = CRegString(L"Software\\TortoiseGit\\History\\SubmoduleUpdatePath\\" + WorkingDir);
  237. CString path = m_regPath;
  238. STRING_VECTOR emptylist;
  239. STRING_VECTOR list;
  240. GetSubmodulePathList(list, m_bWholeProject ? emptylist : m_PathFilterList);
  241. STRING_VECTOR selected;
  242. if (m_PathList.empty())
  243. {
  244. int pos = 0;
  245. while (pos >= 0)
  246. {
  247. CString part = path.Tokenize(_T("|"), pos);
  248. if (!part.IsEmpty())
  249. selected.push_back(part);
  250. }
  251. }
  252. else
  253. {
  254. for (size_t i = 0; i < m_PathList.size(); ++i)
  255. selected.push_back(m_PathList[i]);
  256. }
  257. for (size_t i = 0; i < list.size(); ++i)
  258. {
  259. m_PathListBox.AddString(list[i]);
  260. if (selected.size() == 0)
  261. m_PathListBox.SetSel((int)i);
  262. else
  263. {
  264. for (size_t j = 0; j < selected.size(); ++j)
  265. {
  266. if (selected[j] == list[i])
  267. m_PathListBox.SetSel((int)i);
  268. }
  269. }
  270. }
  271. OnLbnSelchangeListPath();
  272. }