1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2014 - 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.
21 #include "TortoiseProc.h"
22 #include "SubmoduleUpdateDlg.h"
24 #include "UnicodeUtils.h"
25 #include "MessageBox.h"
27 IMPLEMENT_DYNAMIC(CSubmoduleUpdateDlg
, CStandAloneDialog
)
29 bool CSubmoduleUpdateDlg::s_bSortLogical
= true;
31 CSubmoduleUpdateDlg::CSubmoduleUpdateDlg(CWnd
* pParent
/*=NULL*/)
32 : CStandAloneDialog(CSubmoduleUpdateDlg::IDD
, pParent
)
40 , m_bWholeProject(FALSE
)
42 s_bSortLogical
= !CRegDWORD(L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_CURRENT_USER
);
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 CStandAloneDialog::DoDataExchange(pDX
);
54 DDX_Control(pDX
, IDC_LIST_PATH
, m_PathListBox
);
55 DDX_Control(pDX
, IDC_SELECTALL
, m_SelectAll
);
56 DDX_Check(pDX
, IDC_SHOWWHOLEPROJECT
, 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
);
67 BEGIN_MESSAGE_MAP(CSubmoduleUpdateDlg
, CStandAloneDialog
)
68 ON_BN_CLICKED(IDC_SELECTALL
, OnBnClickedSelectall
)
69 ON_BN_CLICKED(IDC_SHOWWHOLEPROJECT
, OnBnClickedShowWholeProject
)
70 ON_BN_CLICKED(IDOK
, &CSubmoduleUpdateDlg::OnBnClickedOk
)
71 ON_LBN_SELCHANGE(IDC_LIST_PATH
, &CSubmoduleUpdateDlg::OnLbnSelchangeListPath
)
74 static int SubmoduleCallback(git_submodule
*sm
, const char * /*name*/, void *payload
)
76 STRING_VECTOR
*list
= *(STRING_VECTOR
**)payload
;
77 STRING_VECTOR
*prefixList
= *((STRING_VECTOR
**)payload
+ 1);
78 CString path
= CUnicodeUtils::GetUnicode(git_submodule_path(sm
));
79 if (prefixList
->empty())
81 list
->push_back(path
);
85 for (size_t i
= 0; i
< prefixList
->size(); ++i
)
87 CString prefix
= prefixList
->at(i
) + _T("/");
88 if (path
.Left(prefix
.GetLength()) == prefix
)
89 list
->push_back(path
);
95 int LogicalComparePredicate(const CString
&left
, const CString
&right
)
97 if (CSubmoduleUpdateDlg::s_bSortLogical
)
98 return StrCmpLogicalW(left
, right
) < 0;
99 return StrCmpI(left
, right
) < 0;
102 static void GetSubmodulePathList(STRING_VECTOR
&list
, STRING_VECTOR
&prefixList
)
104 CAutoRepository
repo(g_Git
.GetGitRepository());
107 MessageBox(NULL
, CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR
);
111 STRING_VECTOR
*listParams
[] = { &list
, &prefixList
};
112 if (git_submodule_foreach(repo
, SubmoduleCallback
, &listParams
))
114 MessageBox(NULL
, CGit::GetLibGit2LastErr(_T("Could not get submodule list.")), _T("TortoiseGit"), MB_ICONERROR
);
118 std::sort(list
.begin(), list
.end(), LogicalComparePredicate
);
121 BOOL
CSubmoduleUpdateDlg::OnInitDialog()
123 CStandAloneDialog::OnInitDialog();
124 CAppUtils::MarkWindowAsUnpinnable(m_hWnd
);
126 CString
str(g_Git
.m_CurrentDir
);
127 str
.Replace(_T(":"), _T("_"));
128 m_regShowWholeProject
= CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ShowWholeProject\\") + str
, FALSE
);
129 m_bWholeProject
= m_regShowWholeProject
;
131 DialogEnableWindow(IDC_SHOWWHOLEPROJECT
, !(m_PathFilterList
.empty() || (m_PathFilterList
.size() == 1 && m_PathFilterList
[0].IsEmpty())));
135 AdjustControlSize(IDC_CHECK_SUBMODULE_INIT
);
136 AdjustControlSize(IDC_CHECK_SUBMODULE_RECURSIVE
);
137 AdjustControlSize(IDC_CHECK_SUBMODULE_NOFETCH
);
138 AdjustControlSize(IDC_CHECK_SUBMODULE_MERGE
);
139 AdjustControlSize(IDC_CHECK_SUBMODULE_REBASE
);
147 void CSubmoduleUpdateDlg::SetDlgTitle()
149 if (m_sTitle
.IsEmpty())
150 GetWindowText(m_sTitle
);
151 CString dir
= g_Git
.m_CurrentDir
;
152 if (!m_bWholeProject
)
154 if (!m_PathFilterList
.empty())
155 dir
+= (g_Git
.m_CurrentDir
.Right(1) == _T('\\') ? _T("") : _T("\\")) + CTGitPath(m_PathFilterList
[0]).GetWinPathString();
156 if (m_PathFilterList
.size() > 1)
159 CAppUtils::SetWindowTitle(m_hWnd
, dir
, m_sTitle
);
162 void CSubmoduleUpdateDlg::OnBnClickedOk()
164 CStandAloneDialog::UpdateData(TRUE
);
166 if (m_bRemote
&& CAppUtils::GetMsysgitVersion() < 0x01080200)
169 gitver
.Format(IDS_GITVER_REQUIRED
, _T("--remote"), _T("1.8.2"));
170 CMessageBox::Show(m_hWnd
, gitver
, _T("TortoiseGit"), MB_OK
| MB_ICONERROR
);
175 for (int i
= 0; i
< m_PathListBox
.GetCount(); ++i
)
177 if (m_PathListBox
.GetSel(i
))
179 if (!selected
.IsEmpty())
180 selected
.Append(_T("|"));
182 m_PathListBox
.GetText(i
, text
);
183 m_PathList
.push_back(text
);
184 selected
.Append(text
);
187 m_regPath
= selected
;
189 CStandAloneDialog::OnOK();
192 void CSubmoduleUpdateDlg::OnLbnSelchangeListPath()
194 GetDlgItem(IDOK
)->EnableWindow(m_PathListBox
.GetSelCount() > 0 ? TRUE
: FALSE
);
195 if (m_PathListBox
.GetSelCount() == 0)
196 m_SelectAll
.SetCheck(BST_UNCHECKED
);
197 else if ((int)m_PathListBox
.GetSelCount() < m_PathListBox
.GetCount())
198 m_SelectAll
.SetCheck(BST_INDETERMINATE
);
200 m_SelectAll
.SetCheck(BST_CHECKED
);
203 void CSubmoduleUpdateDlg::OnBnClickedSelectall()
205 UINT state
= (m_SelectAll
.GetState() & 0x0003);
206 if (state
== BST_INDETERMINATE
)
208 // It is not at all useful to manually place the checkbox into the indeterminate state...
209 // We will force this on to the unchecked state
210 state
= BST_UNCHECKED
;
211 m_SelectAll
.SetCheck(state
);
213 if (state
== BST_UNCHECKED
)
215 for (int i
= 0; i
< m_PathListBox
.GetCount(); ++i
)
216 m_PathListBox
.SetSel(i
, FALSE
);
220 for (int i
= 0; i
< m_PathListBox
.GetCount(); ++i
)
221 m_PathListBox
.SetSel(i
, TRUE
);
225 void CSubmoduleUpdateDlg::OnBnClickedShowWholeProject()
228 m_regShowWholeProject
= m_bWholeProject
;
233 void CSubmoduleUpdateDlg::Refresh()
235 while (m_PathListBox
.GetCount() > 0)
236 m_PathListBox
.DeleteString(m_PathListBox
.GetCount() - 1);
238 CString WorkingDir
= g_Git
.m_CurrentDir
;
239 WorkingDir
.Replace(_T(':'), _T('_'));
241 m_regPath
= CRegString(CString(_T("Software\\TortoiseGit\\History\\SubmoduleUpdatePath\\") + WorkingDir
));
242 CString path
= m_regPath
;
243 STRING_VECTOR emptylist
;
245 GetSubmodulePathList(list
, m_bWholeProject
? emptylist
: m_PathFilterList
);
246 STRING_VECTOR selected
;
247 if (m_PathList
.empty())
252 CString part
= path
.Tokenize(_T("|"), pos
);
254 selected
.push_back(part
);
259 for (size_t i
= 0; i
< m_PathList
.size(); ++i
)
260 selected
.push_back(m_PathList
[i
]);
263 for (size_t i
= 0; i
< list
.size(); ++i
)
265 m_PathListBox
.AddString(list
[i
]);
266 if (selected
.size() == 0)
267 m_PathListBox
.SetSel((int)i
);
270 for (size_t j
= 0; j
< selected
.size(); ++j
)
272 if (selected
[j
] == list
[i
])
273 m_PathListBox
.SetSel((int)i
);
278 OnLbnSelchangeListPath();