Merge branch 'restructure-tree'
[TortoiseGit.git] / src / TortoiseProc / EditPropertiesDlg.cpp
blob65ef4d7eccadde07fdac65b5cce572f34ae79780
1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008,2011 - TortoiseSVN
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.
19 #include "stdafx.h"
20 #include "SVNProperties.h"
21 #include "MessageBox.h"
22 #include "TortoiseProc.h"
23 #include "EditPropertiesDlg.h"
24 #include "EditPropertyValueDlg.h"
25 #include "UnicodeUtils.h"
26 #include "PathUtils.h"
27 #include "AppUtils.h"
28 #include "StringUtils.h"
29 #include "ProgressDlg.h"
30 #include "InputLogDlg.h"
31 #include "XPTheme.h"
34 IMPLEMENT_DYNAMIC(CEditPropertiesDlg, CResizableStandAloneDialog)
36 CEditPropertiesDlg::CEditPropertiesDlg(CWnd* pParent /*=NULL*/)
37 : CResizableStandAloneDialog(CEditPropertiesDlg::IDD, pParent)
38 , m_bRecursive(FALSE)
39 , m_bChanged(false)
40 , m_revision(SVNRev::REV_WC)
41 , m_bRevProps(false)
45 CEditPropertiesDlg::~CEditPropertiesDlg()
49 void CEditPropertiesDlg::DoDataExchange(CDataExchange* pDX)
51 CResizableStandAloneDialog::DoDataExchange(pDX);
52 DDX_Control(pDX, IDC_EDITPROPLIST, m_propList);
56 BEGIN_MESSAGE_MAP(CEditPropertiesDlg, CResizableStandAloneDialog)
57 ON_BN_CLICKED(IDHELP, &CEditPropertiesDlg::OnBnClickedHelp)
58 ON_NOTIFY(NM_CUSTOMDRAW, IDC_EDITPROPLIST, &CEditPropertiesDlg::OnNMCustomdrawEditproplist)
59 ON_BN_CLICKED(IDC_REMOVEPROPS, &CEditPropertiesDlg::OnBnClickedRemoveProps)
60 ON_BN_CLICKED(IDC_EDITPROPS, &CEditPropertiesDlg::OnBnClickedEditprops)
61 ON_NOTIFY(LVN_ITEMCHANGED, IDC_EDITPROPLIST, &CEditPropertiesDlg::OnLvnItemchangedEditproplist)
62 ON_NOTIFY(NM_DBLCLK, IDC_EDITPROPLIST, &CEditPropertiesDlg::OnNMDblclkEditproplist)
63 ON_BN_CLICKED(IDC_SAVEPROP, &CEditPropertiesDlg::OnBnClickedSaveprop)
64 ON_BN_CLICKED(IDC_ADDPROPS, &CEditPropertiesDlg::OnBnClickedAddprops)
65 ON_BN_CLICKED(IDC_EXPORT, &CEditPropertiesDlg::OnBnClickedExport)
66 ON_BN_CLICKED(IDC_IMPORT, &CEditPropertiesDlg::OnBnClickedImport)
67 END_MESSAGE_MAP()
69 void CEditPropertiesDlg::OnBnClickedHelp()
71 OnHelp();
74 BOOL CEditPropertiesDlg::OnInitDialog()
76 CResizableStandAloneDialog::OnInitDialog();
78 // fill in the path edit control
79 if (m_pathlist.GetCount() == 1)
81 if (m_pathlist[0].IsUrl())
82 SetDlgItemText(IDC_PROPPATH, m_pathlist[0].GetSVNPathString());
83 else
84 SetDlgItemText(IDC_PROPPATH, m_pathlist[0].GetWinPathString());
86 else
88 CString sTemp;
89 sTemp.Format(IDS_EDITPROPS_NUMPATHS, m_pathlist.GetCount());
90 SetDlgItemText(IDC_PROPPATH, sTemp);
93 CXPTheme theme;
94 theme.SetWindowTheme(m_propList.GetSafeHwnd(), L"Explorer", NULL);
96 // initialize the property list control
97 m_propList.DeleteAllItems();
98 DWORD exStyle = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER;
99 m_propList.SetExtendedStyle(exStyle);
100 int c = ((CHeaderCtrl*)(m_propList.GetDlgItem(0)))->GetItemCount()-1;
101 while (c>=0)
102 m_propList.DeleteColumn(c--);
103 CString temp;
104 temp.LoadString(IDS_PROPPROPERTY);
105 m_propList.InsertColumn(0, temp);
106 temp.LoadString(IDS_PROPVALUE);
107 m_propList.InsertColumn(1, temp);
108 m_propList.SetRedraw(false);
110 if (m_bRevProps)
112 GetDlgItem(IDC_IMPORT)->ShowWindow(SW_HIDE);
113 GetDlgItem(IDC_EXPORT)->ShowWindow(SW_HIDE);
116 m_tooltips.Create(this);
117 m_tooltips.AddTool(IDC_IMPORT, IDS_PROP_TT_IMPORT);
118 m_tooltips.AddTool(IDC_EXPORT, IDS_PROP_TT_EXPORT);
119 m_tooltips.AddTool(IDC_SAVEPROP, IDS_PROP_TT_SAVE);
120 m_tooltips.AddTool(IDC_REMOVEPROPS, IDS_PROP_TT_REMOVE);
121 m_tooltips.AddTool(IDC_EDITPROPS, IDS_PROP_TT_EDIT);
122 m_tooltips.AddTool(IDC_ADDPROPS, IDS_PROP_TT_ADD);
124 AddAnchor(IDC_GROUP, TOP_LEFT, BOTTOM_RIGHT);
125 AddAnchor(IDC_PROPPATH, TOP_LEFT, TOP_RIGHT);
126 AddAnchor(IDC_EDITPROPLIST, TOP_LEFT, BOTTOM_RIGHT);
127 AddAnchor(IDC_IMPORT, BOTTOM_RIGHT);
128 AddAnchor(IDC_EXPORT, BOTTOM_RIGHT);
129 AddAnchor(IDC_SAVEPROP, BOTTOM_RIGHT);
130 AddAnchor(IDC_REMOVEPROPS, BOTTOM_RIGHT);
131 AddAnchor(IDC_EDITPROPS, BOTTOM_RIGHT);
132 AddAnchor(IDC_ADDPROPS, BOTTOM_RIGHT);
133 AddAnchor(IDOK, BOTTOM_RIGHT);
134 AddAnchor(IDHELP, BOTTOM_RIGHT);
135 if (hWndExplorer)
136 CenterWindow(CWnd::FromHandle(hWndExplorer));
137 EnableSaveRestore(_T("EditPropertiesDlg"));
139 InterlockedExchange(&m_bThreadRunning, TRUE);
140 if (AfxBeginThread(PropsThreadEntry, this)==NULL)
142 InterlockedExchange(&m_bThreadRunning, FALSE);
143 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
145 GetDlgItem(IDC_EDITPROPLIST)->SetFocus();
147 return FALSE;
150 void CEditPropertiesDlg::Refresh()
152 if (m_bThreadRunning)
153 return;
154 m_propList.DeleteAllItems();
155 InterlockedExchange(&m_bThreadRunning, TRUE);
156 if (AfxBeginThread(PropsThreadEntry, this)==NULL)
158 InterlockedExchange(&m_bThreadRunning, FALSE);
159 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
163 UINT CEditPropertiesDlg::PropsThreadEntry(LPVOID pVoid)
165 return ((CEditPropertiesDlg*)pVoid)->PropsThread();
168 UINT CEditPropertiesDlg::PropsThread()
170 // get all properties
171 m_properties.clear();
172 for (int i=0; i<m_pathlist.GetCount(); ++i)
174 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
175 for (int p=0; p<props.GetCount(); ++p)
177 wide_string prop_str = props.GetItemName(p);
178 std::string prop_value = props.GetItemValue(p);
179 std::map<stdstring,PropValue>::iterator it = m_properties.lower_bound(prop_str);
180 if (it != m_properties.end() && it->first == prop_str)
182 it->second.count++;
183 if (it->second.value.compare(prop_value)!=0)
184 it->second.allthesamevalue = false;
186 else
188 it = m_properties.insert(it, std::make_pair(prop_str, PropValue()));
189 stdstring value = MultibyteToWide((char *)prop_value.c_str());
190 it->second.value = prop_value;
191 CString stemp = value.c_str();
192 stemp.Replace('\n', ' ');
193 stemp.Remove('\r');
194 it->second.value_without_newlines = stdstring((LPCTSTR)stemp);
195 it->second.count = 1;
196 it->second.allthesamevalue = true;
197 if (SVNProperties::IsBinary(prop_value))
198 it->second.isbinary = true;
203 // fill the property list control with the gathered information
204 int index=0;
205 m_propList.SetRedraw(FALSE);
206 for (std::map<stdstring,PropValue>::iterator it = m_properties.begin(); it != m_properties.end(); ++it)
208 m_propList.InsertItem(index, it->first.c_str());
209 if (it->second.isbinary)
211 m_propList.SetItemText(index, 1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_BINVALUE)));
212 m_propList.SetItemData(index, FALSE);
214 else if (it->second.count != m_pathlist.GetCount())
216 // if the property values are the same for all paths they're set
217 // but they're not set for *all* paths, then we show the entry grayed out
218 m_propList.SetItemText(index, 1, it->second.value_without_newlines.c_str());
219 m_propList.SetItemData(index, FALSE);
221 else if (it->second.allthesamevalue)
223 // if the property values are the same for all paths,
224 // we show the value
225 m_propList.SetItemText(index, 1, it->second.value_without_newlines.c_str());
226 m_propList.SetItemData(index, TRUE);
228 else
230 // if the property values aren't the same for all paths
231 // then we show "values are different" instead of the value
232 CString sTemp(MAKEINTRESOURCE(IDS_EDITPROPS_DIFFERENTPROPVALUES));
233 m_propList.SetItemText(index, 1, sTemp);
234 m_propList.SetItemData(index, FALSE);
236 if (index == 0)
238 // select the first entry
239 m_propList.SetItemState(index, LVIS_SELECTED, LVIS_SELECTED);
240 m_propList.SetSelectionMark(index);
242 index++;
244 int maxcol = ((CHeaderCtrl*)(m_propList.GetDlgItem(0)))->GetItemCount()-1;
245 for (int col = 0; col <= maxcol; col++)
247 m_propList.SetColumnWidth(col, LVSCW_AUTOSIZE_USEHEADER);
250 InterlockedExchange(&m_bThreadRunning, FALSE);
251 m_propList.SetRedraw(TRUE);
252 return 0;
255 void CEditPropertiesDlg::OnNMCustomdrawEditproplist(NMHDR *pNMHDR, LRESULT *pResult)
257 NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
258 // Take the default processing unless we set this to something else below.
259 *pResult = CDRF_DODEFAULT;
261 if (m_bThreadRunning)
262 return;
264 // First thing - check the draw stage. If it's the control's prepaint
265 // stage, then tell Windows we want messages for every item.
267 if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
269 *pResult = CDRF_NOTIFYITEMDRAW;
271 else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
273 // This is the prepaint stage for an item. Here's where we set the
274 // item's text color. Our return value will tell Windows to draw the
275 // item itself, but it will use the new color we set here.
277 // Tell Windows to paint the control itself.
278 *pResult = CDRF_DODEFAULT;
280 if ((int)pLVCD->nmcd.dwItemSpec > m_propList.GetItemCount())
281 return;
283 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
284 if (m_propList.GetItemData (static_cast<int>(pLVCD->nmcd.dwItemSpec))==FALSE)
285 crText = GetSysColor(COLOR_GRAYTEXT);
286 // Store the color back in the NMLVCUSTOMDRAW struct.
287 pLVCD->clrText = crText;
292 void CEditPropertiesDlg::OnLvnItemchangedEditproplist(NMHDR * /*pNMHDR*/, LRESULT *pResult)
294 *pResult = 0;
295 // disable the "remove" button if nothing
296 // is selected, enable it otherwise
297 int selCount = m_propList.GetSelectedCount();
298 DialogEnableWindow(IDC_EXPORT, selCount >= 1);
299 DialogEnableWindow(IDC_REMOVEPROPS, selCount >= 1);
300 DialogEnableWindow(IDC_SAVEPROP, selCount == 1);
301 DialogEnableWindow(IDC_EDITPROPS, selCount == 1);
303 *pResult = 0;
306 void CEditPropertiesDlg::OnBnClickedRemoveProps()
308 CString sLogMsg;
309 POSITION pos = m_propList.GetFirstSelectedItemPosition();
310 while ( pos )
312 int selIndex = m_propList.GetNextSelectedItem(pos);
314 bool bRecurse = false;
315 CString sName = m_propList.GetItemText(selIndex, 0);
316 if (m_pathlist[0].IsUrl())
318 CInputLogDlg input(this);
319 input.SetUUID(m_sUUID);
320 input.SetProjectProperties(m_pProjectProperties);
321 CString sHint;
322 sHint.Format(IDS_INPUT_REMOVEPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));
323 input.SetActionText(sHint);
324 if (input.DoModal() != IDOK)
325 return;
326 sLogMsg = input.GetLogMessage();
328 CString sQuestion;
329 sQuestion.Format(IDS_EDITPROPS_RECURSIVEREMOVEQUESTION, (LPCTSTR)sName);
330 CString sRecursive(MAKEINTRESOURCE(IDS_EDITPROPS_RECURSIVE));
331 CString sNotRecursive(MAKEINTRESOURCE(IDS_EDITPROPS_NOTRECURSIVE));
332 CString sCancel(MAKEINTRESOURCE(IDS_EDITPROPS_CANCEL));
334 if ((m_pathlist.GetCount()>1)||((m_pathlist.GetCount()==1)&&(PathIsDirectory(m_pathlist[0].GetWinPath()))))
336 int ret = CMessageBox::Show(m_hWnd, sQuestion, _T("TortoiseSVN"), MB_DEFBUTTON1, IDI_QUESTION, sRecursive, sNotRecursive, sCancel);
337 if (ret == 1)
338 bRecurse = true;
339 else if (ret == 2)
340 bRecurse = false;
341 else
342 break;
345 CProgressDlg prog;
346 CString sTemp;
347 sTemp.LoadString(IDS_SETPROPTITLE);
348 prog.SetTitle(sTemp);
349 sTemp.LoadString(IDS_PROPWAITCANCEL);
350 prog.SetCancelMsg(sTemp);
351 prog.SetTime(TRUE);
352 prog.SetShowProgressBar(TRUE);
353 prog.ShowModeless(m_hWnd);
354 for (int i=0; i<m_pathlist.GetCount(); ++i)
356 prog.SetLine(1, m_pathlist[i].GetWinPath(), true);
357 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
358 if (!props.Remove(sName, bRecurse ? svn_depth_infinity : svn_depth_empty, (LPCTSTR)sLogMsg))
360 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);
362 else
364 m_bChanged = true;
365 if (m_revision.IsNumber())
366 m_revision = LONG(m_revision)+1;
369 prog.Stop();
371 DialogEnableWindow(IDC_REMOVEPROPS, FALSE);
372 DialogEnableWindow(IDC_SAVEPROP, FALSE);
373 Refresh();
376 void CEditPropertiesDlg::OnNMDblclkEditproplist(NMHDR * /*pNMHDR*/, LRESULT *pResult)
378 if (m_propList.GetSelectedCount() == 1)
379 EditProps();
381 *pResult = 0;
384 void CEditPropertiesDlg::OnBnClickedEditprops()
386 EditProps();
389 void CEditPropertiesDlg::OnBnClickedAddprops()
391 EditProps(true);
394 void CEditPropertiesDlg::EditProps(bool bAdd /* = false*/)
396 m_tooltips.Pop(); // hide the tooltips
397 int selIndex = m_propList.GetSelectionMark();
399 CEditPropertyValueDlg dlg;
400 CString sName;
402 if ((!bAdd)&&(selIndex >= 0)&&(m_propList.GetSelectedCount()))
404 sName = m_propList.GetItemText(selIndex, 0);
405 PropValue& prop = m_properties[stdstring(sName)];
406 dlg.SetPropertyName(sName);
407 if (prop.allthesamevalue)
408 dlg.SetPropertyValue(prop.value);
409 dlg.SetDialogTitle(CString(MAKEINTRESOURCE(IDS_EDITPROPS_EDITTITLE)));
411 else
413 dlg.SetPathList(m_pathlist); // this is the problem
414 dlg.SetDialogTitle(CString(MAKEINTRESOURCE(IDS_EDITPROPS_ADDTITLE)));
417 if (m_pathlist.GetCount() > 1)
418 dlg.SetMultiple();
419 else if (m_pathlist.GetCount() == 1)
421 if (PathIsDirectory(m_pathlist[0].GetWinPath()))
422 dlg.SetFolder();
425 dlg.RevProps(m_bRevProps);
426 if ( dlg.DoModal()==IDOK )
428 sName = dlg.GetPropertyName();
429 if (!sName.IsEmpty())
431 CString sMsg;
432 bool bDoIt = true;
433 if (!m_bRevProps&&(m_pathlist.GetCount())&&(m_pathlist[0].IsUrl()))
435 CInputLogDlg input(this);
436 input.SetUUID(m_sUUID);
437 input.SetProjectProperties(m_pProjectProperties);
438 CString sHint;
439 sHint.Format(IDS_INPUT_EDITPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));
440 input.SetActionText(sHint);
441 if (input.DoModal() == IDOK)
443 sMsg = input.GetLogMessage();
445 else
446 bDoIt = false;
448 if (bDoIt)
450 CProgressDlg prog;
451 CString sTemp;
452 sTemp.LoadString(IDS_SETPROPTITLE);
453 prog.SetTitle(sTemp);
454 sTemp.LoadString(IDS_PROPWAITCANCEL);
455 prog.SetCancelMsg(sTemp);
456 prog.SetTime(TRUE);
457 prog.SetShowProgressBar(TRUE);
458 prog.ShowModeless(m_hWnd);
459 for (int i=0; i<m_pathlist.GetCount(); ++i)
461 prog.SetLine(1, m_pathlist[i].GetWinPath(), true);
462 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
463 if (!props.Add(sName, dlg.IsBinary() ? dlg.GetPropertyValue() : dlg.GetPropertyValue().c_str(),
464 dlg.GetRecursive() ? svn_depth_infinity : svn_depth_empty, sMsg))
466 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);
468 else
470 m_bChanged = true;
471 // bump the revision number since we just did a commit
472 if (!m_bRevProps && m_revision.IsNumber())
473 m_revision = LONG(m_revision)+1;
476 prog.Stop();
477 Refresh();
483 void CEditPropertiesDlg::OnOK()
485 if (m_bThreadRunning)
486 return;
487 CStandAloneDialogTmpl<CResizableDialog>::OnOK();
490 void CEditPropertiesDlg::OnCancel()
492 if (m_bThreadRunning)
493 return;
494 CStandAloneDialogTmpl<CResizableDialog>::OnCancel();
497 BOOL CEditPropertiesDlg::PreTranslateMessage(MSG* pMsg)
499 m_tooltips.RelayEvent(pMsg);
501 if (pMsg->message == WM_KEYDOWN)
503 switch (pMsg->wParam)
505 case VK_F5:
507 if (m_bThreadRunning)
508 return __super::PreTranslateMessage(pMsg);
509 Refresh();
511 break;
512 case VK_RETURN:
514 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
516 if ( GetDlgItem(IDOK)->IsWindowEnabled() )
518 PostMessage(WM_COMMAND, IDOK);
522 break;
523 default:
524 break;
528 return __super::PreTranslateMessage(pMsg);
531 void CEditPropertiesDlg::OnBnClickedSaveprop()
533 m_tooltips.Pop(); // hide the tooltips
534 int selIndex = m_propList.GetSelectionMark();
536 CString sName;
537 CString sValue;
538 if ((selIndex >= 0)&&(m_propList.GetSelectedCount()))
540 sName = m_propList.GetItemText(selIndex, 0);
541 PropValue& prop = m_properties[stdstring(sName)];
542 sValue = prop.value.c_str();
543 if (prop.allthesamevalue)
545 CString savePath;
546 if (!CAppUtils::FileOpenSave(savePath, NULL, IDS_REPOBROWSE_SAVEAS, 0, false, m_hWnd))
547 return;
549 FILE * stream;
550 errno_t err = 0;
551 if ((err = _tfopen_s(&stream, (LPCTSTR)savePath, _T("wbS")))==0)
553 fwrite(prop.value.c_str(), sizeof(char), prop.value.size(), stream);
554 fclose(stream);
556 else
558 TCHAR strErr[4096] = {0};
559 _tcserror_s(strErr, 4096, err);
560 CMessageBox::Show(m_hWnd, strErr, _T("TortoiseSVN"), MB_ICONERROR);
566 void CEditPropertiesDlg::OnBnClickedExport()
568 m_tooltips.Pop(); // hide the tooltips
569 if (m_propList.GetSelectedCount() == 0)
570 return;
572 CString savePath;
573 if (!CAppUtils::FileOpenSave(savePath, NULL, IDS_REPOBROWSE_SAVEAS, IDS_PROPSFILEFILTER, false, m_hWnd))
574 return;
576 if (CPathUtils::GetFileExtFromPath(savePath).Compare(_T(".svnprops")))
578 // append the default ".svnprops" extension since the user did not specify it himself
579 savePath += _T(".svnprops");
581 // we save the list of selected properties not in a text file but in our own
582 // binary format. That's because properties can be binary themselves, a text
583 // or xml file just won't do it properly.
584 CString sName;
585 CString sValue;
586 FILE * stream;
587 errno_t err = 0;
589 if ((err = _tfopen_s(&stream, (LPCTSTR)savePath, _T("wbS")))==0)
591 POSITION pos = m_propList.GetFirstSelectedItemPosition();
592 int len = m_propList.GetSelectedCount();
593 fwrite(&len, sizeof(int), 1, stream); // number of properties
594 while (pos)
596 int index = m_propList.GetNextSelectedItem(pos);
597 sName = m_propList.GetItemText(index, 0);
598 PropValue& prop = m_properties[stdstring(sName)];
599 sValue = prop.value.c_str();
600 int len = sName.GetLength()*sizeof(TCHAR);
601 fwrite(&len, sizeof(int), 1, stream); // length of property name in bytes
602 fwrite(sName, sizeof(TCHAR), sName.GetLength(), stream); // property name
603 len = static_cast<int>(prop.value.size());
604 fwrite(&len, sizeof(int), 1, stream); // length of property value in bytes
605 fwrite(prop.value.c_str(), sizeof(char), prop.value.size(), stream); // property value
607 fclose(stream);
609 else
611 TCHAR strErr[4096] = {0};
612 _tcserror_s(strErr, 4096, err);
613 CMessageBox::Show(m_hWnd, strErr, _T("TortoiseSVN"), MB_ICONERROR);
617 void CEditPropertiesDlg::OnBnClickedImport()
619 m_tooltips.Pop(); // hide the tooltips
620 CString openPath;
621 if (!CAppUtils::FileOpenSave(openPath, NULL, IDS_REPOBROWSE_OPEN, IDS_PROPSFILEFILTER, true, m_hWnd))
623 return;
625 // first check the size of the file
626 FILE * stream;
627 _tfopen_s(&stream, openPath, _T("rbS"));
628 int nProperties = 0;
629 if (fread(&nProperties, sizeof(int), 1, stream) == 1)
631 bool bFailed = false;
632 if ((nProperties < 0)||(nProperties > 4096))
634 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
635 bFailed = true;
637 CProgressDlg prog;
638 CString sTemp;
639 sTemp.LoadString(IDS_SETPROPTITLE);
640 prog.SetTitle(sTemp);
641 sTemp.LoadString(IDS_PROPWAITCANCEL);
642 prog.SetCancelMsg(sTemp);
643 prog.SetTime(TRUE);
644 prog.SetShowProgressBar(TRUE);
645 prog.ShowModeless(m_hWnd);
646 while ((nProperties-- > 0)&&(!bFailed))
648 int nNameBytes = 0;
649 if ((nNameBytes < 0)||(nNameBytes > 4096))
651 prog.Stop();
652 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
653 bFailed = true;
655 if (fread(&nNameBytes, sizeof(int), 1, stream) == 1)
657 TCHAR * pNameBuf = new TCHAR[nNameBytes/sizeof(TCHAR)];
658 if (fread(pNameBuf, 1, nNameBytes, stream) == (size_t)nNameBytes)
660 CString sName = CString(pNameBuf, nNameBytes/sizeof(TCHAR));
661 int nValueBytes = 0;
662 if (fread(&nValueBytes, sizeof(int), 1, stream) == 1)
664 BYTE * pValueBuf = new BYTE[nValueBytes];
665 if (fread(pValueBuf, sizeof(char), nValueBytes, stream) == (size_t)nValueBytes)
667 std::string propertyvalue;
668 propertyvalue.assign((const char*)pValueBuf, nValueBytes);
669 CString sMsg;
670 if (m_pathlist[0].IsUrl())
672 CInputLogDlg input(this);
673 input.SetUUID(m_sUUID);
674 input.SetProjectProperties(m_pProjectProperties);
675 CString sHint;
676 sHint.Format(IDS_INPUT_SETPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));
677 input.SetActionText(sHint);
678 if (input.DoModal() == IDOK)
680 sMsg = input.GetLogMessage();
682 else
683 bFailed = true;
686 for (int i=0; i<m_pathlist.GetCount() && !bFailed; ++i)
688 prog.SetLine(1, m_pathlist[i].GetWinPath(), true);
689 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
690 if (!props.Add(sName, propertyvalue, svn_depth_empty, (LPCTSTR)sMsg))
692 prog.Stop();
693 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);
694 bFailed = true;
696 else
698 if (m_revision.IsNumber())
699 m_revision = (LONG)m_revision + 1;
703 else
705 prog.Stop();
706 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
707 bFailed = true;
709 delete [] pValueBuf;
711 else
713 prog.Stop();
714 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
715 bFailed = true;
718 else
720 prog.Stop();
721 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
722 bFailed = true;
724 delete [] pNameBuf;
726 else
728 prog.Stop();
729 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
730 bFailed = true;
733 prog.Stop();
734 fclose(stream);
737 Refresh();