remove the XPTheme wrapper class since we now require at least XP and don't need...
[TortoiseGit.git] / src / TortoiseProc / EditPropertiesDlg.cpp
blob57150c36203e579da77c4f29e452f784b8478086
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"
33 IMPLEMENT_DYNAMIC(CEditPropertiesDlg, CResizableStandAloneDialog)
35 CEditPropertiesDlg::CEditPropertiesDlg(CWnd* pParent /*=NULL*/)
36 : CResizableStandAloneDialog(CEditPropertiesDlg::IDD, pParent)
37 , m_bRecursive(FALSE)
38 , m_bChanged(false)
39 , m_revision(SVNRev::REV_WC)
40 , m_bRevProps(false)
41 , m_pProjectProperties(NULL)
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 SetWindowTheme(m_hWnd, L"Explorer", NULL);
95 // initialize the property list control
96 m_propList.DeleteAllItems();
97 DWORD exStyle = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER;
98 m_propList.SetExtendedStyle(exStyle);
99 int c = ((CHeaderCtrl*)(m_propList.GetDlgItem(0)))->GetItemCount()-1;
100 while (c>=0)
101 m_propList.DeleteColumn(c--);
102 CString temp;
103 temp.LoadString(IDS_PROPPROPERTY);
104 m_propList.InsertColumn(0, temp);
105 temp.LoadString(IDS_PROPVALUE);
106 m_propList.InsertColumn(1, temp);
107 m_propList.SetRedraw(false);
109 if (m_bRevProps)
111 GetDlgItem(IDC_IMPORT)->ShowWindow(SW_HIDE);
112 GetDlgItem(IDC_EXPORT)->ShowWindow(SW_HIDE);
115 m_tooltips.Create(this);
116 m_tooltips.AddTool(IDC_IMPORT, IDS_PROP_TT_IMPORT);
117 m_tooltips.AddTool(IDC_EXPORT, IDS_PROP_TT_EXPORT);
118 m_tooltips.AddTool(IDC_SAVEPROP, IDS_PROP_TT_SAVE);
119 m_tooltips.AddTool(IDC_REMOVEPROPS, IDS_PROP_TT_REMOVE);
120 m_tooltips.AddTool(IDC_EDITPROPS, IDS_PROP_TT_EDIT);
121 m_tooltips.AddTool(IDC_ADDPROPS, IDS_PROP_TT_ADD);
123 AddAnchor(IDC_GROUP, TOP_LEFT, BOTTOM_RIGHT);
124 AddAnchor(IDC_PROPPATH, TOP_LEFT, TOP_RIGHT);
125 AddAnchor(IDC_EDITPROPLIST, TOP_LEFT, BOTTOM_RIGHT);
126 AddAnchor(IDC_IMPORT, BOTTOM_RIGHT);
127 AddAnchor(IDC_EXPORT, BOTTOM_RIGHT);
128 AddAnchor(IDC_SAVEPROP, BOTTOM_RIGHT);
129 AddAnchor(IDC_REMOVEPROPS, BOTTOM_RIGHT);
130 AddAnchor(IDC_EDITPROPS, BOTTOM_RIGHT);
131 AddAnchor(IDC_ADDPROPS, BOTTOM_RIGHT);
132 AddAnchor(IDOK, BOTTOM_RIGHT);
133 AddAnchor(IDHELP, BOTTOM_RIGHT);
134 if (hWndExplorer)
135 CenterWindow(CWnd::FromHandle(hWndExplorer));
136 EnableSaveRestore(_T("EditPropertiesDlg"));
138 InterlockedExchange(&m_bThreadRunning, TRUE);
139 if (AfxBeginThread(PropsThreadEntry, this)==NULL)
141 InterlockedExchange(&m_bThreadRunning, FALSE);
142 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
144 GetDlgItem(IDC_EDITPROPLIST)->SetFocus();
146 return FALSE;
149 void CEditPropertiesDlg::Refresh()
151 if (m_bThreadRunning)
152 return;
153 m_propList.DeleteAllItems();
154 InterlockedExchange(&m_bThreadRunning, TRUE);
155 if (AfxBeginThread(PropsThreadEntry, this)==NULL)
157 InterlockedExchange(&m_bThreadRunning, FALSE);
158 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
162 UINT CEditPropertiesDlg::PropsThreadEntry(LPVOID pVoid)
164 return ((CEditPropertiesDlg*)pVoid)->PropsThread();
167 UINT CEditPropertiesDlg::PropsThread()
169 // get all properties
170 m_properties.clear();
171 for (int i=0; i<m_pathlist.GetCount(); ++i)
173 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
174 for (int p=0; p<props.GetCount(); ++p)
176 wide_string prop_str = props.GetItemName(p);
177 std::string prop_value = props.GetItemValue(p);
178 std::map<stdstring,PropValue>::iterator it = m_properties.lower_bound(prop_str);
179 if (it != m_properties.end() && it->first == prop_str)
181 it->second.count++;
182 if (it->second.value.compare(prop_value)!=0)
183 it->second.allthesamevalue = false;
185 else
187 it = m_properties.insert(it, std::make_pair(prop_str, PropValue()));
188 stdstring value = MultibyteToWide((char *)prop_value.c_str());
189 it->second.value = prop_value;
190 CString stemp = value.c_str();
191 stemp.Replace('\n', ' ');
192 stemp.Remove('\r');
193 it->second.value_without_newlines = stdstring((LPCTSTR)stemp);
194 it->second.count = 1;
195 it->second.allthesamevalue = true;
196 if (SVNProperties::IsBinary(prop_value))
197 it->second.isbinary = true;
202 // fill the property list control with the gathered information
203 int index=0;
204 m_propList.SetRedraw(FALSE);
205 for (std::map<stdstring,PropValue>::iterator it = m_properties.begin(); it != m_properties.end(); ++it)
207 m_propList.InsertItem(index, it->first.c_str());
208 if (it->second.isbinary)
210 m_propList.SetItemText(index, 1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_BINVALUE)));
211 m_propList.SetItemData(index, FALSE);
213 else if (it->second.count != m_pathlist.GetCount())
215 // if the property values are the same for all paths they're set
216 // but they're not set for *all* paths, then we show the entry grayed out
217 m_propList.SetItemText(index, 1, it->second.value_without_newlines.c_str());
218 m_propList.SetItemData(index, FALSE);
220 else if (it->second.allthesamevalue)
222 // if the property values are the same for all paths,
223 // we show the value
224 m_propList.SetItemText(index, 1, it->second.value_without_newlines.c_str());
225 m_propList.SetItemData(index, TRUE);
227 else
229 // if the property values aren't the same for all paths
230 // then we show "values are different" instead of the value
231 CString sTemp(MAKEINTRESOURCE(IDS_EDITPROPS_DIFFERENTPROPVALUES));
232 m_propList.SetItemText(index, 1, sTemp);
233 m_propList.SetItemData(index, FALSE);
235 if (index == 0)
237 // select the first entry
238 m_propList.SetItemState(index, LVIS_SELECTED, LVIS_SELECTED);
239 m_propList.SetSelectionMark(index);
241 index++;
243 int maxcol = ((CHeaderCtrl*)(m_propList.GetDlgItem(0)))->GetItemCount()-1;
244 for (int col = 0; col <= maxcol; col++)
246 m_propList.SetColumnWidth(col, LVSCW_AUTOSIZE_USEHEADER);
249 InterlockedExchange(&m_bThreadRunning, FALSE);
250 m_propList.SetRedraw(TRUE);
251 return 0;
254 void CEditPropertiesDlg::OnNMCustomdrawEditproplist(NMHDR *pNMHDR, LRESULT *pResult)
256 NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
257 // Take the default processing unless we set this to something else below.
258 *pResult = CDRF_DODEFAULT;
260 if (m_bThreadRunning)
261 return;
263 // First thing - check the draw stage. If it's the control's prepaint
264 // stage, then tell Windows we want messages for every item.
266 if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
268 *pResult = CDRF_NOTIFYITEMDRAW;
270 else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
272 // This is the prepaint stage for an item. Here's where we set the
273 // item's text color. Our return value will tell Windows to draw the
274 // item itself, but it will use the new color we set here.
276 // Tell Windows to paint the control itself.
277 *pResult = CDRF_DODEFAULT;
279 if ((int)pLVCD->nmcd.dwItemSpec > m_propList.GetItemCount())
280 return;
282 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
283 if (m_propList.GetItemData (static_cast<int>(pLVCD->nmcd.dwItemSpec))==FALSE)
284 crText = GetSysColor(COLOR_GRAYTEXT);
285 // Store the color back in the NMLVCUSTOMDRAW struct.
286 pLVCD->clrText = crText;
291 void CEditPropertiesDlg::OnLvnItemchangedEditproplist(NMHDR * /*pNMHDR*/, LRESULT *pResult)
293 *pResult = 0;
294 // disable the "remove" button if nothing
295 // is selected, enable it otherwise
296 int selCount = m_propList.GetSelectedCount();
297 DialogEnableWindow(IDC_EXPORT, selCount >= 1);
298 DialogEnableWindow(IDC_REMOVEPROPS, selCount >= 1);
299 DialogEnableWindow(IDC_SAVEPROP, selCount == 1);
300 DialogEnableWindow(IDC_EDITPROPS, selCount == 1);
302 *pResult = 0;
305 void CEditPropertiesDlg::OnBnClickedRemoveProps()
307 CString sLogMsg;
308 POSITION pos = m_propList.GetFirstSelectedItemPosition();
309 while ( pos )
311 int selIndex = m_propList.GetNextSelectedItem(pos);
313 bool bRecurse = false;
314 CString sName = m_propList.GetItemText(selIndex, 0);
315 if (m_pathlist[0].IsUrl())
317 CInputLogDlg input(this);
318 input.SetUUID(m_sUUID);
319 input.SetProjectProperties(m_pProjectProperties);
320 CString sHint;
321 sHint.Format(IDS_INPUT_REMOVEPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));
322 input.SetActionText(sHint);
323 if (input.DoModal() != IDOK)
324 return;
325 sLogMsg = input.GetLogMessage();
327 CString sQuestion;
328 sQuestion.Format(IDS_EDITPROPS_RECURSIVEREMOVEQUESTION, (LPCTSTR)sName);
329 CString sRecursive(MAKEINTRESOURCE(IDS_EDITPROPS_RECURSIVE));
330 CString sNotRecursive(MAKEINTRESOURCE(IDS_EDITPROPS_NOTRECURSIVE));
331 CString sCancel(MAKEINTRESOURCE(IDS_EDITPROPS_CANCEL));
333 if ((m_pathlist.GetCount()>1)||((m_pathlist.GetCount()==1)&&(PathIsDirectory(m_pathlist[0].GetWinPath()))))
335 int ret = CMessageBox::Show(m_hWnd, sQuestion, _T("TortoiseSVN"), MB_DEFBUTTON1, IDI_QUESTION, sRecursive, sNotRecursive, sCancel);
336 if (ret == 1)
337 bRecurse = true;
338 else if (ret == 2)
339 bRecurse = false;
340 else
341 break;
344 CProgressDlg prog;
345 CString sTemp;
346 sTemp.LoadString(IDS_SETPROPTITLE);
347 prog.SetTitle(sTemp);
348 sTemp.LoadString(IDS_PROPWAITCANCEL);
349 prog.SetCancelMsg(sTemp);
350 prog.SetTime(TRUE);
351 prog.SetShowProgressBar(TRUE);
352 prog.ShowModeless(m_hWnd);
353 for (int i=0; i<m_pathlist.GetCount(); ++i)
355 prog.SetLine(1, m_pathlist[i].GetWinPath(), true);
356 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
357 if (!props.Remove(sName, bRecurse ? svn_depth_infinity : svn_depth_empty, (LPCTSTR)sLogMsg))
359 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);
361 else
363 m_bChanged = true;
364 if (m_revision.IsNumber())
365 m_revision = LONG(m_revision)+1;
368 prog.Stop();
370 DialogEnableWindow(IDC_REMOVEPROPS, FALSE);
371 DialogEnableWindow(IDC_SAVEPROP, FALSE);
372 Refresh();
375 void CEditPropertiesDlg::OnNMDblclkEditproplist(NMHDR * /*pNMHDR*/, LRESULT *pResult)
377 if (m_propList.GetSelectedCount() == 1)
378 EditProps();
380 *pResult = 0;
383 void CEditPropertiesDlg::OnBnClickedEditprops()
385 EditProps();
388 void CEditPropertiesDlg::OnBnClickedAddprops()
390 EditProps(true);
393 void CEditPropertiesDlg::EditProps(bool bAdd /* = false*/)
395 m_tooltips.Pop(); // hide the tooltips
396 int selIndex = m_propList.GetSelectionMark();
398 CEditPropertyValueDlg dlg;
399 CString sName;
401 if ((!bAdd)&&(selIndex >= 0)&&(m_propList.GetSelectedCount()))
403 sName = m_propList.GetItemText(selIndex, 0);
404 PropValue& prop = m_properties[stdstring(sName)];
405 dlg.SetPropertyName(sName);
406 if (prop.allthesamevalue)
407 dlg.SetPropertyValue(prop.value);
408 dlg.SetDialogTitle(CString(MAKEINTRESOURCE(IDS_EDITPROPS_EDITTITLE)));
410 else
412 dlg.SetPathList(m_pathlist); // this is the problem
413 dlg.SetDialogTitle(CString(MAKEINTRESOURCE(IDS_EDITPROPS_ADDTITLE)));
416 if (m_pathlist.GetCount() > 1)
417 dlg.SetMultiple();
418 else if (m_pathlist.GetCount() == 1)
420 if (PathIsDirectory(m_pathlist[0].GetWinPath()))
421 dlg.SetFolder();
424 dlg.RevProps(m_bRevProps);
425 if ( dlg.DoModal()==IDOK )
427 sName = dlg.GetPropertyName();
428 if (!sName.IsEmpty())
430 CString sMsg;
431 bool bDoIt = true;
432 if (!m_bRevProps&&(m_pathlist.GetCount())&&(m_pathlist[0].IsUrl()))
434 CInputLogDlg input(this);
435 input.SetUUID(m_sUUID);
436 input.SetProjectProperties(m_pProjectProperties);
437 CString sHint;
438 sHint.Format(IDS_INPUT_EDITPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));
439 input.SetActionText(sHint);
440 if (input.DoModal() == IDOK)
442 sMsg = input.GetLogMessage();
444 else
445 bDoIt = false;
447 if (bDoIt)
449 CProgressDlg prog;
450 CString sTemp;
451 sTemp.LoadString(IDS_SETPROPTITLE);
452 prog.SetTitle(sTemp);
453 sTemp.LoadString(IDS_PROPWAITCANCEL);
454 prog.SetCancelMsg(sTemp);
455 prog.SetTime(TRUE);
456 prog.SetShowProgressBar(TRUE);
457 prog.ShowModeless(m_hWnd);
458 for (int i=0; i<m_pathlist.GetCount(); ++i)
460 prog.SetLine(1, m_pathlist[i].GetWinPath(), true);
461 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
462 if (!props.Add(sName, dlg.IsBinary() ? dlg.GetPropertyValue() : dlg.GetPropertyValue().c_str(),
463 dlg.GetRecursive() ? svn_depth_infinity : svn_depth_empty, sMsg))
465 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);
467 else
469 m_bChanged = true;
470 // bump the revision number since we just did a commit
471 if (!m_bRevProps && m_revision.IsNumber())
472 m_revision = LONG(m_revision)+1;
475 prog.Stop();
476 Refresh();
482 void CEditPropertiesDlg::OnOK()
484 if (m_bThreadRunning)
485 return;
486 CStandAloneDialogTmpl<CResizableDialog>::OnOK();
489 void CEditPropertiesDlg::OnCancel()
491 if (m_bThreadRunning)
492 return;
493 CStandAloneDialogTmpl<CResizableDialog>::OnCancel();
496 BOOL CEditPropertiesDlg::PreTranslateMessage(MSG* pMsg)
498 m_tooltips.RelayEvent(pMsg);
500 if (pMsg->message == WM_KEYDOWN)
502 switch (pMsg->wParam)
504 case VK_F5:
506 if (m_bThreadRunning)
507 return __super::PreTranslateMessage(pMsg);
508 Refresh();
510 break;
511 case VK_RETURN:
513 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
515 if ( GetDlgItem(IDOK)->IsWindowEnabled() )
517 PostMessage(WM_COMMAND, IDOK);
521 break;
522 default:
523 break;
527 return __super::PreTranslateMessage(pMsg);
530 void CEditPropertiesDlg::OnBnClickedSaveprop()
532 m_tooltips.Pop(); // hide the tooltips
533 int selIndex = m_propList.GetSelectionMark();
535 CString sName;
536 CString sValue;
537 if ((selIndex >= 0)&&(m_propList.GetSelectedCount()))
539 sName = m_propList.GetItemText(selIndex, 0);
540 PropValue& prop = m_properties[stdstring(sName)];
541 sValue = prop.value.c_str();
542 if (prop.allthesamevalue)
544 CString savePath;
545 if (!CAppUtils::FileOpenSave(savePath, NULL, IDS_REPOBROWSE_SAVEAS, 0, false, m_hWnd))
546 return;
548 FILE * stream;
549 errno_t err = 0;
550 if ((err = _tfopen_s(&stream, (LPCTSTR)savePath, _T("wbS")))==0)
552 fwrite(prop.value.c_str(), sizeof(char), prop.value.size(), stream);
553 fclose(stream);
555 else
557 TCHAR strErr[4096] = {0};
558 _tcserror_s(strErr, 4096, err);
559 CMessageBox::Show(m_hWnd, strErr, _T("TortoiseSVN"), MB_ICONERROR);
565 void CEditPropertiesDlg::OnBnClickedExport()
567 m_tooltips.Pop(); // hide the tooltips
568 if (m_propList.GetSelectedCount() == 0)
569 return;
571 CString savePath;
572 if (!CAppUtils::FileOpenSave(savePath, NULL, IDS_REPOBROWSE_SAVEAS, IDS_PROPSFILEFILTER, false, m_hWnd))
573 return;
575 if (CPathUtils::GetFileExtFromPath(savePath).Compare(_T(".svnprops")))
577 // append the default ".svnprops" extension since the user did not specify it himself
578 savePath += _T(".svnprops");
580 // we save the list of selected properties not in a text file but in our own
581 // binary format. That's because properties can be binary themselves, a text
582 // or xml file just won't do it properly.
583 CString sName;
584 CString sValue;
585 FILE * stream;
586 errno_t err = 0;
588 if ((err = _tfopen_s(&stream, (LPCTSTR)savePath, _T("wbS")))==0)
590 POSITION pos = m_propList.GetFirstSelectedItemPosition();
591 int len = m_propList.GetSelectedCount();
592 fwrite(&len, sizeof(int), 1, stream); // number of properties
593 while (pos)
595 int index = m_propList.GetNextSelectedItem(pos);
596 sName = m_propList.GetItemText(index, 0);
597 PropValue& prop = m_properties[stdstring(sName)];
598 sValue = prop.value.c_str();
599 int len = sName.GetLength()*sizeof(TCHAR);
600 fwrite(&len, sizeof(int), 1, stream); // length of property name in bytes
601 fwrite(sName, sizeof(TCHAR), sName.GetLength(), stream); // property name
602 len = static_cast<int>(prop.value.size());
603 fwrite(&len, sizeof(int), 1, stream); // length of property value in bytes
604 fwrite(prop.value.c_str(), sizeof(char), prop.value.size(), stream); // property value
606 fclose(stream);
608 else
610 TCHAR strErr[4096] = {0};
611 _tcserror_s(strErr, 4096, err);
612 CMessageBox::Show(m_hWnd, strErr, _T("TortoiseSVN"), MB_ICONERROR);
616 void CEditPropertiesDlg::OnBnClickedImport()
618 m_tooltips.Pop(); // hide the tooltips
619 CString openPath;
620 if (!CAppUtils::FileOpenSave(openPath, NULL, IDS_REPOBROWSE_OPEN, IDS_PROPSFILEFILTER, true, m_hWnd))
622 return;
624 // first check the size of the file
625 FILE * stream;
626 _tfopen_s(&stream, openPath, _T("rbS"));
627 int nProperties = 0;
628 if (fread(&nProperties, sizeof(int), 1, stream) == 1)
630 bool bFailed = false;
631 if ((nProperties < 0)||(nProperties > 4096))
633 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
634 bFailed = true;
636 CProgressDlg prog;
637 CString sTemp;
638 sTemp.LoadString(IDS_SETPROPTITLE);
639 prog.SetTitle(sTemp);
640 sTemp.LoadString(IDS_PROPWAITCANCEL);
641 prog.SetCancelMsg(sTemp);
642 prog.SetTime(TRUE);
643 prog.SetShowProgressBar(TRUE);
644 prog.ShowModeless(m_hWnd);
645 while ((nProperties-- > 0)&&(!bFailed))
647 int nNameBytes = 0;
648 if ((nNameBytes < 0)||(nNameBytes > 4096))
650 prog.Stop();
651 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
652 bFailed = true;
654 if (fread(&nNameBytes, sizeof(int), 1, stream) == 1)
656 TCHAR * pNameBuf = new TCHAR[nNameBytes/sizeof(TCHAR)];
657 if (fread(pNameBuf, 1, nNameBytes, stream) == (size_t)nNameBytes)
659 CString sName = CString(pNameBuf, nNameBytes/sizeof(TCHAR));
660 int nValueBytes = 0;
661 if (fread(&nValueBytes, sizeof(int), 1, stream) == 1)
663 BYTE * pValueBuf = new BYTE[nValueBytes];
664 if (fread(pValueBuf, sizeof(char), nValueBytes, stream) == (size_t)nValueBytes)
666 std::string propertyvalue;
667 propertyvalue.assign((const char*)pValueBuf, nValueBytes);
668 CString sMsg;
669 if (m_pathlist[0].IsUrl())
671 CInputLogDlg input(this);
672 input.SetUUID(m_sUUID);
673 input.SetProjectProperties(m_pProjectProperties);
674 CString sHint;
675 sHint.Format(IDS_INPUT_SETPROP, (LPCTSTR)sName, (LPCTSTR)(m_pathlist[0].GetSVNPathString()));
676 input.SetActionText(sHint);
677 if (input.DoModal() == IDOK)
679 sMsg = input.GetLogMessage();
681 else
682 bFailed = true;
685 for (int i=0; i<m_pathlist.GetCount() && !bFailed; ++i)
687 prog.SetLine(1, m_pathlist[i].GetWinPath(), true);
688 SVNProperties props(m_pathlist[i], m_revision, m_bRevProps);
689 if (!props.Add(sName, propertyvalue, svn_depth_empty, (LPCTSTR)sMsg))
691 prog.Stop();
692 CMessageBox::Show(m_hWnd, props.GetLastErrorMsg().c_str(), _T("TortoiseSVN"), MB_ICONERROR);
693 bFailed = true;
695 else
697 if (m_revision.IsNumber())
698 m_revision = (LONG)m_revision + 1;
702 else
704 prog.Stop();
705 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
706 bFailed = true;
708 delete [] pValueBuf;
710 else
712 prog.Stop();
713 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
714 bFailed = true;
717 else
719 prog.Stop();
720 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
721 bFailed = true;
723 delete [] pNameBuf;
725 else
727 prog.Stop();
728 CMessageBox::Show(m_hWnd, IDS_EDITPROPS_ERRIMPORTFORMAT, IDS_APPNAME, MB_ICONERROR);
729 bFailed = true;
732 prog.Stop();
733 fclose(stream);
736 Refresh();