OSDN Git Service

SyncDlg show animate when press push button and hide input control.
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / EditPropertiesDlg.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "stdafx.h"\r
20 #include "SVNProperties.h"\r
21 #include "MessageBox.h"\r
22 #include "TortoiseProc.h"\r
23 #include "EditPropertiesDlg.h"\r
24 #include "EditPropertyValueDlg.h"\r
25 #include "UnicodeUtils.h"\r
26 #include "PathUtils.h"\r
27 #include "AppUtils.h"\r
28 #include "StringUtils.h"\r
29 #include "ProgressDlg.h"\r
30 #include "InputLogDlg.h"\r
31 #include "XPTheme.h"\r
32 \r
33 \r
34 IMPLEMENT_DYNAMIC(CEditPropertiesDlg, CResizableStandAloneDialog)\r
35 \r
36 CEditPropertiesDlg::CEditPropertiesDlg(CWnd* pParent /*=NULL*/)\r
37         : CResizableStandAloneDialog(CEditPropertiesDlg::IDD, pParent)\r
38         , m_bRecursive(FALSE)\r
39         , m_bChanged(false)\r
40         , m_revision(SVNRev::REV_WC)\r
41         , m_bRevProps(false)\r
42 {\r
43 }\r
44 \r
45 CEditPropertiesDlg::~CEditPropertiesDlg()\r
46 {\r
47 }\r
48 \r
49 void CEditPropertiesDlg::DoDataExchange(CDataExchange* pDX)\r
50 {\r
51         CResizableStandAloneDialog::DoDataExchange(pDX);\r
52         DDX_Control(pDX, IDC_EDITPROPLIST, m_propList);\r
53 }\r
54 \r
55 \r
56 BEGIN_MESSAGE_MAP(CEditPropertiesDlg, CResizableStandAloneDialog)\r
57         ON_BN_CLICKED(IDHELP, &CEditPropertiesDlg::OnBnClickedHelp)\r
58         ON_NOTIFY(NM_CUSTOMDRAW, IDC_EDITPROPLIST, &CEditPropertiesDlg::OnNMCustomdrawEditproplist)\r
59         ON_BN_CLICKED(IDC_REMOVEPROPS, &CEditPropertiesDlg::OnBnClickedRemoveProps)\r
60         ON_BN_CLICKED(IDC_EDITPROPS, &CEditPropertiesDlg::OnBnClickedEditprops)\r
61         ON_NOTIFY(LVN_ITEMCHANGED, IDC_EDITPROPLIST, &CEditPropertiesDlg::OnLvnItemchangedEditproplist)\r
62         ON_NOTIFY(NM_DBLCLK, IDC_EDITPROPLIST, &CEditPropertiesDlg::OnNMDblclkEditproplist)\r
63         ON_BN_CLICKED(IDC_SAVEPROP, &CEditPropertiesDlg::OnBnClickedSaveprop)\r
64         ON_BN_CLICKED(IDC_ADDPROPS, &CEditPropertiesDlg::OnBnClickedAddprops)\r
65         ON_BN_CLICKED(IDC_EXPORT, &CEditPropertiesDlg::OnBnClickedExport)\r
66         ON_BN_CLICKED(IDC_IMPORT, &CEditPropertiesDlg::OnBnClickedImport)\r
67 END_MESSAGE_MAP()\r
68 \r
69 void CEditPropertiesDlg::OnBnClickedHelp()\r
70 {\r
71         OnHelp();\r
72 }\r
73 \r
74 BOOL CEditPropertiesDlg::OnInitDialog()\r
75 {\r
76         CResizableStandAloneDialog::OnInitDialog();\r
77 \r
78         // fill in the path edit control\r
79         if (m_pathlist.GetCount() == 1)\r
80         {\r
81                 if (m_pathlist[0].IsUrl())\r
82                         SetDlgItemText(IDC_PROPPATH, m_pathlist[0].GetSVNPathString());\r
83                 else\r
84                         SetDlgItemText(IDC_PROPPATH, m_pathlist[0].GetWinPathString());\r
85         }\r
86         else\r
87         {\r
88                 CString sTemp;\r
89                 sTemp.Format(IDS_EDITPROPS_NUMPATHS, m_pathlist.GetCount());\r
90                 SetDlgItemText(IDC_PROPPATH, sTemp);\r
91         }\r
92 \r
93         CXPTheme theme;\r
94         theme.SetWindowTheme(m_propList.GetSafeHwnd(), L"Explorer", NULL);\r
95 \r
96         // initialize the property list control\r
97         m_propList.DeleteAllItems();\r
98         DWORD exStyle = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER;\r
99         m_propList.SetExtendedStyle(exStyle);\r
100         int c = ((CHeaderCtrl*)(m_propList.GetDlgItem(0)))->GetItemCount()-1;\r
101         while (c>=0)\r
102                 m_propList.DeleteColumn(c--);\r
103         CString temp;\r
104         temp.LoadString(IDS_PROPPROPERTY);\r
105         m_propList.InsertColumn(0, temp);\r
106         temp.LoadString(IDS_PROPVALUE);\r
107         m_propList.InsertColumn(1, temp);\r
108         m_propList.SetRedraw(false);\r
109 \r
110         if (m_bRevProps)\r
111         {\r
112                 GetDlgItem(IDC_IMPORT)->ShowWindow(SW_HIDE);\r
113                 GetDlgItem(IDC_EXPORT)->ShowWindow(SW_HIDE);\r
114         }\r
115 \r
116         m_tooltips.Create(this);\r
117         m_tooltips.AddTool(IDC_IMPORT, IDS_PROP_TT_IMPORT);\r
118         m_tooltips.AddTool(IDC_EXPORT,  IDS_PROP_TT_EXPORT);\r
119         m_tooltips.AddTool(IDC_SAVEPROP,  IDS_PROP_TT_SAVE);\r
120         m_tooltips.AddTool(IDC_REMOVEPROPS,  IDS_PROP_TT_REMOVE);\r
121         m_tooltips.AddTool(IDC_EDITPROPS,  IDS_PROP_TT_EDIT);\r
122         m_tooltips.AddTool(IDC_ADDPROPS,  IDS_PROP_TT_ADD);\r
123 \r
124         AddAnchor(IDC_GROUP, TOP_LEFT, BOTTOM_RIGHT);\r
125         AddAnchor(IDC_PROPPATH, TOP_LEFT, TOP_RIGHT);\r
126         AddAnchor(IDC_EDITPROPLIST, TOP_LEFT, BOTTOM_RIGHT);\r
127         AddAnchor(IDC_IMPORT, BOTTOM_RIGHT);\r
128         AddAnchor(IDC_EXPORT, BOTTOM_RIGHT);\r
129         AddAnchor(IDC_SAVEPROP, BOTTOM_RIGHT);\r
130         AddAnchor(IDC_REMOVEPROPS, BOTTOM_RIGHT);\r
131         AddAnchor(IDC_EDITPROPS, BOTTOM_RIGHT);\r
132         AddAnchor(IDC_ADDPROPS, BOTTOM_RIGHT);\r
133         AddAnchor(IDOK, BOTTOM_RIGHT);\r
134         AddAnchor(IDHELP, BOTTOM_RIGHT);\r
135         if (hWndExplorer)\r
136                 CenterWindow(CWnd::FromHandle(hWndExplorer));\r
137         EnableSaveRestore(_T("EditPropertiesDlg"));\r
138 \r
139         InterlockedExchange(&m_bThreadRunning, TRUE);\r
140         if (AfxBeginThread(PropsThreadEntry, this)==NULL)\r
141         {\r
142                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
143                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
144         }\r
145         GetDlgItem(IDC_EDITPROPLIST)->SetFocus();\r
146 \r
147         return FALSE;\r
148 }\r
149 \r
150 void CEditPropertiesDlg::Refresh()\r
151 {\r
152         if (m_bThreadRunning)\r
153                 return;\r
154         m_propList.DeleteAllItems();\r
155         InterlockedExchange(&m_bThreadRunning, TRUE);\r
156         if (AfxBeginThread(PropsThreadEntry, this)==NULL)\r
157         {\r
158                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
159                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
160         }\r
161 }\r
162 \r
163 UINT CEditPropertiesDlg::PropsThreadEntry(LPVOID pVoid)\r
164 {\r
165         return ((CEditPropertiesDlg*)pVoid)->PropsThread();\r
166 }\r
167 \r
168 UINT CEditPropertiesDlg::PropsThread()\r
169 {\r
170         // get all properties\r
171         m_properties.clear();\r
172         for (int i=0; i<m_pathlist.GetCount(); ++i)\r
173         {\r
174                 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);\r
175                 for (int p=0; p<props.GetCount(); ++p)\r
176                 {\r
177                         wide_string prop_str = props.GetItemName(p);\r
178                         std::string prop_value = props.GetItemValue(p);\r
179                         std::map<stdstring,PropValue>::iterator it = m_properties.lower_bound(prop_str);\r
180                         if (it != m_properties.end() && it->first == prop_str)\r
181                         {\r
182                                 it->second.count++;\r
183                                 if (it->second.value.compare(prop_value)!=0)\r
184                                         it->second.allthesamevalue = false;\r
185                         }\r
186                         else\r
187                         {\r
188                                 it = m_properties.insert(it, std::make_pair(prop_str, PropValue()));\r
189                                 stdstring value = MultibyteToWide((char *)prop_value.c_str());\r
190                                 it->second.value = prop_value;\r
191                                 CString stemp = value.c_str();\r
192                                 stemp.Replace('\n', ' ');\r
193                                 stemp.Replace(_T("\r"), _T(""));\r
194                                 it->second.value_without_newlines = stdstring((LPCTSTR)stemp);\r
195                                 it->second.count = 1;\r
196                                 it->second.allthesamevalue = true;\r
197                                 if (SVNProperties::IsBinary(prop_value))\r
198                                         it->second.isbinary = true;\r
199                         }\r
200                 }\r
201         }\r
202         \r
203         // fill the property list control with the gathered information\r
204         int index=0;\r
205         m_propList.SetRedraw(FALSE);\r
206         for (std::map<stdstring,PropValue>::iterator it = m_properties.begin(); it != m_properties.end(); ++it)\r
207         {\r
208                 m_propList.InsertItem(index, it->first.c_str());\r
209                 if (it->second.isbinary)\r
210                 {\r
211                         m_propList.SetItemText(index, 1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_BINVALUE)));\r
212                         m_propList.SetItemData(index, FALSE);\r
213                 }\r
214                 else if (it->second.count != m_pathlist.GetCount())\r
215                 {\r
216                         // if the property values are the same for all paths they're set\r
217                         // but they're not set for *all* paths, then we show the entry grayed out\r
218                         m_propList.SetItemText(index, 1, it->second.value_without_newlines.c_str());\r
219                         m_propList.SetItemData(index, FALSE);\r
220                 }\r
221                 else if (it->second.allthesamevalue)\r
222                 {\r
223                         // if the property values are the same for all paths,\r
224                         // we show the value\r
225                         m_propList.SetItemText(index, 1, it->second.value_without_newlines.c_str());\r
226                         m_propList.SetItemData(index, TRUE);\r
227                 }\r
228                 else\r
229                 {\r
230                         // if the property values aren't the same for all paths\r
231                         // then we show "values are different" instead of the value\r
232                         CString sTemp(MAKEINTRESOURCE(IDS_EDITPROPS_DIFFERENTPROPVALUES));\r
233                         m_propList.SetItemText(index, 1, sTemp);\r
234                         m_propList.SetItemData(index, FALSE);\r
235                 }\r
236                 if (index == 0)\r
237                 {\r
238                         // select the first entry\r
239                         m_propList.SetItemState(index, LVIS_SELECTED, LVIS_SELECTED);\r
240                         m_propList.SetSelectionMark(index);\r
241                 }\r
242                 index++;\r
243         }\r
244         int maxcol = ((CHeaderCtrl*)(m_propList.GetDlgItem(0)))->GetItemCount()-1;\r
245         for (int col = 0; col <= maxcol; col++)\r
246         {\r
247                 m_propList.SetColumnWidth(col, LVSCW_AUTOSIZE_USEHEADER);\r
248         }\r
249 \r
250         InterlockedExchange(&m_bThreadRunning, FALSE);\r
251         m_propList.SetRedraw(TRUE);\r
252         return 0;\r
253 }\r
254 \r
255 void CEditPropertiesDlg::OnNMCustomdrawEditproplist(NMHDR *pNMHDR, LRESULT *pResult)\r
256 {\r
257         NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );\r
258         // Take the default processing unless we set this to something else below.\r
259         *pResult = CDRF_DODEFAULT;\r
260 \r
261         if (m_bThreadRunning)\r
262                 return;\r
263 \r
264         // First thing - check the draw stage. If it's the control's prepaint\r
265         // stage, then tell Windows we want messages for every item.\r
266 \r
267         if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )\r
268         {\r
269                 *pResult = CDRF_NOTIFYITEMDRAW;\r
270         }\r
271         else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )\r
272         {\r
273                 // This is the prepaint stage for an item. Here's where we set the\r
274                 // item's text color. Our return value will tell Windows to draw the\r
275                 // item itself, but it will use the new color we set here.\r
276 \r
277                 // Tell Windows to paint the control itself.\r
278                 *pResult = CDRF_DODEFAULT;\r
279 \r
280                 if ((int)pLVCD->nmcd.dwItemSpec > m_propList.GetItemCount())\r
281                         return;\r
282 \r
283                 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);\r
284                 if (m_propList.GetItemData (static_cast<int>(pLVCD->nmcd.dwItemSpec))==FALSE)\r
285                         crText = GetSysColor(COLOR_GRAYTEXT);\r
286                 // Store the color back in the NMLVCUSTOMDRAW struct.\r
287                 pLVCD->clrText = crText;\r
288         }\r
289 \r
290 }\r
291 \r
292 void CEditPropertiesDlg::OnLvnItemchangedEditproplist(NMHDR * /*pNMHDR*/, LRESULT *pResult)\r
293 {\r
294         *pResult = 0;\r
295         // disable the "remove" button if nothing\r
296         // is selected, enable it otherwise\r
297         int selCount = m_propList.GetSelectedCount();\r
298         DialogEnableWindow(IDC_EXPORT, selCount >= 1);\r
299         DialogEnableWindow(IDC_REMOVEPROPS, selCount >= 1);\r
300         DialogEnableWindow(IDC_SAVEPROP, selCount == 1);\r
301         DialogEnableWindow(IDC_EDITPROPS, selCount == 1);\r
302 \r
303         *pResult = 0;\r
304 }\r
305 \r
306 void CEditPropertiesDlg::OnBnClickedRemoveProps()\r
307 {\r
308         CString sLogMsg;\r
309         POSITION pos = m_propList.GetFirstSelectedItemPosition();\r
310         while ( pos )\r
311         {\r
312                 int selIndex = m_propList.GetNextSelectedItem(pos);\r
313 \r
314                 bool bRecurse = false;\r
315                 CString sName = m_propList.GetItemText(selIndex, 0);\r
316                 if (m_pathlist[0].IsUrl())\r
317                 {\r
318                         CInputLogDlg input(this);\r
319                         input.SetUUID(m_sUUID);\r
320                         input.SetProjectProperties(m_pProjectProperties);\r
321                         CString sHint;\r
322                         sHint.Format(IDS_INPUT_REMOVEPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));\r
323                         input.SetActionText(sHint);\r
324                         if (input.DoModal() != IDOK)\r
325                                 return;\r
326                         sLogMsg = input.GetLogMessage();\r
327                 }\r
328                 CString sQuestion;\r
329                 sQuestion.Format(IDS_EDITPROPS_RECURSIVEREMOVEQUESTION, (LPCTSTR)sName);\r
330                 CString sRecursive(MAKEINTRESOURCE(IDS_EDITPROPS_RECURSIVE));\r
331                 CString sNotRecursive(MAKEINTRESOURCE(IDS_EDITPROPS_NOTRECURSIVE));\r
332                 CString sCancel(MAKEINTRESOURCE(IDS_EDITPROPS_CANCEL));\r
333 \r
334                 if ((m_pathlist.GetCount()>1)||((m_pathlist.GetCount()==1)&&(PathIsDirectory(m_pathlist[0].GetWinPath()))))\r
335                 {\r
336                         int ret = CMessageBox::Show(m_hWnd, sQuestion, _T("TortoiseSVN"), MB_DEFBUTTON1, IDI_QUESTION, sRecursive, sNotRecursive, sCancel);\r
337                         if (ret == 1)\r
338                                 bRecurse = true;\r
339                         else if (ret == 2)\r
340                                 bRecurse = false;\r
341                         else\r
342                                 break;\r
343                 }\r
344 \r
345                 CProgressDlg prog;\r
346                 CString sTemp;\r
347                 sTemp.LoadString(IDS_SETPROPTITLE);\r
348                 prog.SetTitle(sTemp);\r
349                 sTemp.LoadString(IDS_PROPWAITCANCEL);\r
350                 prog.SetCancelMsg(sTemp);\r
351                 prog.SetTime(TRUE);\r
352                 prog.SetShowProgressBar(TRUE);\r
353                 prog.ShowModeless(m_hWnd);\r
354                 for (int i=0; i<m_pathlist.GetCount(); ++i)\r
355                 {\r
356                         prog.SetLine(1, m_pathlist[i].GetWinPath(), true);\r
357                         SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);\r
358                         if (!props.Remove(sName, bRecurse ? svn_depth_infinity : svn_depth_empty, (LPCTSTR)sLogMsg))\r
359                         {\r
360                                 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);\r
361                         }\r
362                         else\r
363                         {\r
364                                 m_bChanged = true;\r
365                                 if (m_revision.IsNumber())\r
366                                         m_revision = LONG(m_revision)+1;\r
367                         }\r
368                 }\r
369                 prog.Stop();\r
370         }\r
371         DialogEnableWindow(IDC_REMOVEPROPS, FALSE);\r
372         DialogEnableWindow(IDC_SAVEPROP, FALSE);\r
373         Refresh();\r
374 }\r
375 \r
376 void CEditPropertiesDlg::OnNMDblclkEditproplist(NMHDR * /*pNMHDR*/, LRESULT *pResult)\r
377 {\r
378         if (m_propList.GetSelectedCount() == 1)\r
379                 EditProps();\r
380 \r
381         *pResult = 0;\r
382 }\r
383 \r
384 void CEditPropertiesDlg::OnBnClickedEditprops()\r
385 {\r
386         EditProps();\r
387 }\r
388 \r
389 void CEditPropertiesDlg::OnBnClickedAddprops()\r
390 {\r
391         EditProps(true);\r
392 }\r
393 \r
394 void CEditPropertiesDlg::EditProps(bool bAdd /* = false*/)\r
395 {\r
396         m_tooltips.Pop();       // hide the tooltips\r
397         int selIndex = m_propList.GetSelectionMark();\r
398 \r
399         CEditPropertyValueDlg dlg;\r
400         CString sName;\r
401 \r
402         if ((!bAdd)&&(selIndex >= 0)&&(m_propList.GetSelectedCount()))\r
403         {\r
404                 sName = m_propList.GetItemText(selIndex, 0);\r
405                 PropValue& prop = m_properties[stdstring(sName)];\r
406                 dlg.SetPropertyName(sName);\r
407                 if (prop.allthesamevalue)\r
408                         dlg.SetPropertyValue(prop.value);\r
409                 dlg.SetDialogTitle(CString(MAKEINTRESOURCE(IDS_EDITPROPS_EDITTITLE)));\r
410         }\r
411         else\r
412         {\r
413                 dlg.SetPathList(m_pathlist);  // this is the problem\r
414                 dlg.SetDialogTitle(CString(MAKEINTRESOURCE(IDS_EDITPROPS_ADDTITLE)));\r
415         }\r
416 \r
417         if (m_pathlist.GetCount() > 1)\r
418                 dlg.SetMultiple();\r
419         else if (m_pathlist.GetCount() == 1)\r
420         {\r
421                 if (PathIsDirectory(m_pathlist[0].GetWinPath()))\r
422                         dlg.SetFolder();\r
423         }\r
424 \r
425         dlg.RevProps(m_bRevProps);\r
426         if ( dlg.DoModal()==IDOK )\r
427         {\r
428                 sName = dlg.GetPropertyName();\r
429                 if (!sName.IsEmpty())\r
430                 {\r
431                         CString sMsg;\r
432                         bool bDoIt = true;\r
433                         if (!m_bRevProps&&(m_pathlist.GetCount())&&(m_pathlist[0].IsUrl()))\r
434                         {\r
435                                 CInputLogDlg input(this);\r
436                                 input.SetUUID(m_sUUID);\r
437                                 input.SetProjectProperties(m_pProjectProperties);\r
438                                 CString sHint;\r
439                                 sHint.Format(IDS_INPUT_EDITPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));\r
440                                 input.SetActionText(sHint);\r
441                                 if (input.DoModal() == IDOK)\r
442                                 {\r
443                                         sMsg = input.GetLogMessage();\r
444                                 }\r
445                                 else\r
446                                         bDoIt = false;\r
447                         }\r
448                         if (bDoIt)\r
449                         {\r
450                                 CProgressDlg prog;\r
451                                 CString sTemp;\r
452                                 sTemp.LoadString(IDS_SETPROPTITLE);\r
453                                 prog.SetTitle(sTemp);\r
454                                 sTemp.LoadString(IDS_PROPWAITCANCEL);\r
455                                 prog.SetCancelMsg(sTemp);\r
456                                 prog.SetTime(TRUE);\r
457                                 prog.SetShowProgressBar(TRUE);\r
458                                 prog.ShowModeless(m_hWnd);\r
459                                 for (int i=0; i<m_pathlist.GetCount(); ++i)\r
460                                 {\r
461                                         prog.SetLine(1, m_pathlist[i].GetWinPath(), true);\r
462                                         SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);\r
463                                         if (!props.Add(sName, dlg.IsBinary() ? dlg.GetPropertyValue() : dlg.GetPropertyValue().c_str(), \r
464                                                 dlg.GetRecursive() ? svn_depth_infinity : svn_depth_empty, sMsg))\r
465                                         {\r
466                                                 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);\r
467                                         }\r
468                                         else\r
469                                         {\r
470                                                 m_bChanged = true;\r
471                                                 // bump the revision number since we just did a commit\r
472                                                 if (!m_bRevProps && m_revision.IsNumber())\r
473                                                         m_revision = LONG(m_revision)+1;\r
474                                         }\r
475                                 }\r
476                                 prog.Stop();\r
477                                 Refresh();\r
478                         }\r
479                 }\r
480         }\r
481 }\r
482 \r
483 void CEditPropertiesDlg::OnOK()\r
484 {\r
485         if (m_bThreadRunning)\r
486                 return;\r
487         CStandAloneDialogTmpl<CResizableDialog>::OnOK();\r
488 }\r
489 \r
490 void CEditPropertiesDlg::OnCancel()\r
491 {\r
492         if (m_bThreadRunning)\r
493                 return;\r
494         CStandAloneDialogTmpl<CResizableDialog>::OnCancel();\r
495 }\r
496 \r
497 BOOL CEditPropertiesDlg::PreTranslateMessage(MSG* pMsg)\r
498 {\r
499         m_tooltips.RelayEvent(pMsg);\r
500 \r
501         if (pMsg->message == WM_KEYDOWN)\r
502         {\r
503                 switch (pMsg->wParam)\r
504                 {\r
505                 case VK_F5:\r
506                         {\r
507                                 if (m_bThreadRunning)\r
508                                         return __super::PreTranslateMessage(pMsg);\r
509                                 Refresh();\r
510                         }\r
511                         break;\r
512                 case VK_RETURN:\r
513                         {\r
514                                 if (GetAsyncKeyState(VK_CONTROL)&0x8000)\r
515                                 {\r
516                                         if ( GetDlgItem(IDOK)->IsWindowEnabled() )\r
517                                         {\r
518                                                 PostMessage(WM_COMMAND, IDOK);\r
519                                         }\r
520                                 }\r
521                         }\r
522                         break;\r
523                 default:\r
524                         break;\r
525                 }\r
526         }\r
527 \r
528         return __super::PreTranslateMessage(pMsg);\r
529 }\r
530 \r
531 void CEditPropertiesDlg::OnBnClickedSaveprop()\r
532 {\r
533         m_tooltips.Pop();       // hide the tooltips\r
534         int selIndex = m_propList.GetSelectionMark();\r
535 \r
536         CString sName;\r
537         CString sValue;\r
538         if ((selIndex >= 0)&&(m_propList.GetSelectedCount()))\r
539         {\r
540                 sName = m_propList.GetItemText(selIndex, 0);\r
541                 PropValue& prop = m_properties[stdstring(sName)];\r
542                 sValue = prop.value.c_str();\r
543                 if (prop.allthesamevalue)\r
544                 {\r
545                         CString savePath;\r
546                         if (!CAppUtils::FileOpenSave(savePath, NULL, IDS_REPOBROWSE_SAVEAS, 0, false, m_hWnd))\r
547                                 return;\r
548 \r
549                         FILE * stream;\r
550                         errno_t err = 0;\r
551                         if ((err = _tfopen_s(&stream, (LPCTSTR)savePath, _T("wbS")))==0)\r
552                         {\r
553                                 fwrite(prop.value.c_str(), sizeof(char), prop.value.size(), stream);\r
554                                 fclose(stream);\r
555                         }\r
556                         else\r
557                         {\r
558                                 TCHAR strErr[4096] = {0};\r
559                                 _tcserror_s(strErr, 4096, err);\r
560                                 CMessageBox::Show(m_hWnd, strErr, _T("TortoiseSVN"), MB_ICONERROR);\r
561                         }\r
562                 }\r
563         }\r
564 }\r
565 \r
566 void CEditPropertiesDlg::OnBnClickedExport()\r
567 {\r
568         m_tooltips.Pop();       // hide the tooltips\r
569         if (m_propList.GetSelectedCount() == 0)\r
570                 return;\r
571 \r
572         CString savePath;\r
573         if (!CAppUtils::FileOpenSave(savePath, NULL, IDS_REPOBROWSE_SAVEAS, IDS_PROPSFILEFILTER, false, m_hWnd))\r
574                 return;\r
575 \r
576         if (CPathUtils::GetFileExtFromPath(savePath).Compare(_T(".svnprops")))\r
577         {\r
578                 // append the default ".svnprops" extension since the user did not specify it himself\r
579                 savePath += _T(".svnprops");\r
580         }\r
581         // we save the list of selected properties not in a text file but in our own\r
582         // binary format. That's because properties can be binary themselves, a text\r
583         // or xml file just won't do it properly.\r
584         CString sName;\r
585         CString sValue;\r
586         FILE * stream;\r
587         errno_t err = 0;\r
588 \r
589         if ((err = _tfopen_s(&stream, (LPCTSTR)savePath, _T("wbS")))==0)\r
590         {\r
591                 POSITION pos = m_propList.GetFirstSelectedItemPosition();\r
592                 int len = m_propList.GetSelectedCount();\r
593                 fwrite(&len, sizeof(int), 1, stream);                                                                           // number of properties\r
594                 while (pos)\r
595                 {\r
596                         int index = m_propList.GetNextSelectedItem(pos);\r
597                         sName = m_propList.GetItemText(index, 0);\r
598                         PropValue& prop = m_properties[stdstring(sName)];\r
599                         sValue = prop.value.c_str();\r
600                         int len = sName.GetLength()*sizeof(TCHAR);\r
601                         fwrite(&len, sizeof(int), 1, stream);                                                                   // length of property name in bytes\r
602                         fwrite(sName, sizeof(TCHAR), sName.GetLength(), stream);                                // property name\r
603                         len = static_cast<int>(prop.value.size());\r
604                         fwrite(&len, sizeof(int), 1, stream);                                                                   // length of property value in bytes\r
605                         fwrite(prop.value.c_str(), sizeof(char), prop.value.size(), stream);    // property value\r
606                 }\r
607                 fclose(stream);\r
608         }\r
609         else\r
610         {\r
611                 TCHAR strErr[4096] = {0};\r
612                 _tcserror_s(strErr, 4096, err);\r
613                 CMessageBox::Show(m_hWnd, strErr, _T("TortoiseSVN"), MB_ICONERROR);\r
614         }\r
615 }\r
616 \r
617 void CEditPropertiesDlg::OnBnClickedImport()\r
618 {\r
619         m_tooltips.Pop();       // hide the tooltips\r
620         CString openPath;\r
621         if (!CAppUtils::FileOpenSave(openPath, NULL, IDS_REPOBROWSE_OPEN, IDS_PROPSFILEFILTER, true, m_hWnd))\r
622         {\r
623                 return;\r
624         }\r
625         // first check the size of the file\r
626         FILE * stream;\r
627         _tfopen_s(&stream, openPath, _T("rbS"));\r
628         int nProperties = 0;\r
629         if (fread(&nProperties, sizeof(int), 1, stream) == 1)\r
630         {\r
631                 bool bFailed = false;\r
632                 if ((nProperties < 0)||(nProperties > 4096))\r
633                 {\r
634                         CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);\r
635                         bFailed = true;\r
636                 }\r
637                 CProgressDlg prog;\r
638                 CString sTemp;\r
639                 sTemp.LoadString(IDS_SETPROPTITLE);\r
640                 prog.SetTitle(sTemp);\r
641                 sTemp.LoadString(IDS_PROPWAITCANCEL);\r
642                 prog.SetCancelMsg(sTemp);\r
643                 prog.SetTime(TRUE);\r
644                 prog.SetShowProgressBar(TRUE);\r
645                 prog.ShowModeless(m_hWnd);\r
646                 while ((nProperties-- > 0)&&(!bFailed))\r
647                 {\r
648                         int nNameBytes = 0;\r
649                         if ((nNameBytes < 0)||(nNameBytes > 4096))\r
650                         {\r
651                                 prog.Stop();\r
652                                 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);\r
653                                 bFailed = true;\r
654                         }\r
655                         if (fread(&nNameBytes, sizeof(int), 1, stream) == 1)\r
656                         {\r
657                                 TCHAR * pNameBuf = new TCHAR[nNameBytes/sizeof(TCHAR)];\r
658                                 if (fread(pNameBuf, 1, nNameBytes, stream) == (size_t)nNameBytes)\r
659                                 {\r
660                                         CString sName = CString(pNameBuf, nNameBytes/sizeof(TCHAR));\r
661                                         int nValueBytes = 0;\r
662                                         if (fread(&nValueBytes, sizeof(int), 1, stream) == 1)\r
663                                         {\r
664                                                 BYTE * pValueBuf = new BYTE[nValueBytes];\r
665                                                 if (fread(pValueBuf, sizeof(char), nValueBytes, stream) == (size_t)nValueBytes)\r
666                                                 {\r
667                                                         std::string propertyvalue;\r
668                                                         propertyvalue.assign((const char*)pValueBuf, nValueBytes);\r
669                                                         CString sMsg;\r
670                                                         if (m_pathlist[0].IsUrl())\r
671                                                         {\r
672                                                                 CInputLogDlg input(this);\r
673                                                                 input.SetUUID(m_sUUID);\r
674                                                                 input.SetProjectProperties(m_pProjectProperties);\r
675                                                                 CString sHint;\r
676                                                                 sHint.Format(IDS_INPUT_SETPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));\r
677                                                                 input.SetActionText(sHint);\r
678                                                                 if (input.DoModal() == IDOK)\r
679                                                                 {\r
680                                                                         sMsg = input.GetLogMessage();\r
681                                                                 }\r
682                                                                 else\r
683                                                                         bFailed = true;\r
684                                                         }\r
685 \r
686                                                         for (int i=0; i<m_pathlist.GetCount() && !bFailed; ++i)\r
687                                                         {\r
688                                                                 prog.SetLine(1, m_pathlist[i].GetWinPath(), true);\r
689                                                                 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);\r
690                                                                 if (!props.Add(sName, propertyvalue, svn_depth_empty, (LPCTSTR)sMsg))\r
691                                                                 {\r
692                                                                         prog.Stop();\r
693                                                                         CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);\r
694                                                                         bFailed = true;\r
695                                                                 }\r
696                                                                 else\r
697                                                                 {\r
698                                                                         if (m_revision.IsNumber())\r
699                                                                                 m_revision = (LONG)m_revision + 1;\r
700                                                                 }\r
701                                                         }\r
702                                                 }\r
703                                                 else\r
704                                                 {\r
705                                                         prog.Stop();\r
706                                                         CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);\r
707                                                         bFailed = true;\r
708                                                 }\r
709                                                 delete [] pValueBuf;\r
710                                         }\r
711                                         else\r
712                                         {\r
713                                                 prog.Stop();\r
714                                                 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);\r
715                                                 bFailed = true;\r
716                                         }\r
717                                 }\r
718                                 else\r
719                                 {\r
720                                         prog.Stop();\r
721                                         CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);\r
722                                         bFailed = true;\r
723                                 }\r
724                                 delete [] pNameBuf;\r
725                         }\r
726                         else\r
727                         {\r
728                                 prog.Stop();\r
729                                 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);\r
730                                 bFailed = true;\r
731                         }\r
732                 }\r
733                 prog.Stop();\r
734                 fclose(stream);\r
735         }\r
736 \r
737         Refresh();\r
738 }\r