1 // **********************************************************************
3 // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
8 // **********************************************************************
11 #include "PatchClient.h"
12 #include "PatchClientDlg.h"
14 #include <IcePatch2/ClientUtil.h>
23 getBasename(const string
& path
)
25 string::size_type pos
= path
.rfind('/');
26 if(pos
== string::npos
)
28 pos
= path
.rfind('\\');
31 if(pos
== string::npos
)
37 return path
.substr(pos
+ 1);
41 class DialogPatcherFeedback
: public IcePatch2::PatcherFeedback
45 DialogPatcherFeedback(CPatchDlg
* dialog
) :
53 noFileSummary(const string
& reason
)
55 return IDYES
== AfxMessageBox(L
"Cannot load file summary. Perform a thorough patch?", MB_YESNO
|MB_ICONSTOP
);
61 return _dialog
->checksumStart();
65 checksumProgress(const string
& path
)
67 return _dialog
->checksumProgress(path
);
73 return _dialog
->checksumEnd();
79 return _dialog
->fileListStart();
83 fileListProgress(Ice::Int percent
)
85 return _dialog
->fileListProgress(percent
);
91 return _dialog
->fileListEnd();
95 patchStart(const string
& path
, Ice::Long size
, Ice::Long totalProgress
, Ice::Long totalSize
)
97 return _dialog
->patchStart(path
, size
, totalProgress
, totalSize
);
101 patchProgress(Ice::Long progress
, Ice::Long size
, Ice::Long totalProgress
, Ice::Long totalSize
)
103 return _dialog
->patchProgress(progress
, size
, totalProgress
, totalSize
);
110 return _dialog
->patchEnd();
116 return _filesPatched
;
121 CPatchDlg
* const _dialog
;
125 typedef IceUtil::Handle
<DialogPatcherFeedback
> DialogPatcherFeedbackPtr
;
127 CPatchDlg::CPatchDlg(const Ice::CommunicatorPtr
& communicator
, CWnd
* pParent
/*=NULL*/) :
128 CDialog(CPatchDlg::IDD
, pParent
), _communicator(communicator
), _isCancel(false), _isPatch(false)
130 _hIcon
= AfxGetApp()->LoadIcon(IDR_MAINFRAME
);
134 CPatchDlg::checksumStart()
136 _status
->SetWindowText(CString(L
" Calculating checksums..."));
138 _progress
->SetRange(0, 0);
139 _progress
->SetPos(0);
146 CPatchDlg::checksumProgress(const string
& path
)
148 // TODO: indicate busy progress
151 file
.Format(L
" %s", IceUtil::stringToWstring(getBasename(path
)).c_str());
152 _file
->SetWindowText(file
);
159 CPatchDlg::checksumEnd()
166 CPatchDlg::fileListStart()
168 _status
->SetWindowText(CString(L
" Retrieving file list..."));
170 _progress
->SetRange(0, 100);
171 _progress
->SetPos(0);
178 CPatchDlg::fileListProgress(Ice::Int pcnt
)
181 percent
.Format(L
"%d%%", pcnt
);
182 _percent
->SetWindowText(percent
);
184 _progress
->SetPos(pcnt
);
191 CPatchDlg::fileListEnd()
198 CPatchDlg::patchStart(const string
& path
, Ice::Long size
, Ice::Long totalProgress
, Ice::Long totalSize
)
202 _startTime
= IceUtil::Time::now(IceUtil::Time::Monotonic
);
203 _status
->SetWindowText(CString(L
" Patching..."));
204 _speed
->SetWindowText(CString(L
" 0.0 KB/s"));
209 file
.Format(L
" %s", IceUtil::stringToWstring(getBasename(path
)).c_str());
210 _file
->SetWindowText(file
);
212 return patchProgress(0, size
, totalProgress
, totalSize
);
216 CPatchDlg::patchProgress(Ice::Long
, Ice::Long
, Ice::Long totalProgress
, Ice::Long totalSize
)
218 IceUtil::Time elapsed
= IceUtil::Time::now(IceUtil::Time::Monotonic
) - _startTime
;
219 if(elapsed
.toSeconds() > 0)
222 speed
.Format(L
" %s/s", convertSize(totalProgress
/ elapsed
.toSeconds()));
223 _speed
->SetWindowText(speed
);
229 pcnt
= static_cast<int>(totalProgress
* 100 / totalSize
);
232 percent
.Format(L
"%d%%", pcnt
);
233 _percent
->SetWindowText(percent
);
236 total
.Format(L
" %s / %s", convertSize(totalProgress
), convertSize(totalSize
));
237 _total
->SetWindowText(total
);
239 _progress
->SetPos(pcnt
);
246 CPatchDlg::patchEnd()
253 CPatchDlg::DoDataExchange(CDataExchange
* pDX
)
255 CDialog::DoDataExchange(pDX
);
258 BEGIN_MESSAGE_MAP(CPatchDlg
, CDialog
)
260 ON_WM_QUERYDRAGICON()
262 ON_BN_CLICKED(IDC_SELECTDIR
, OnSelectDir
)
263 ON_BN_CLICKED(IDC_STARTPATCH
, OnStartPatch
)
264 ON_BN_CLICKED(IDC_CANCELPATCH
, OnCancel
)
268 CPatchDlg::OnInitDialog()
270 CDialog::OnInitDialog();
272 // Set the icon for this dialog. The framework does this automatically
273 // when the application's main window is not a dialog
274 SetIcon(_hIcon
, TRUE
); // Set big icon
275 SetIcon(_hIcon
, FALSE
); // Set small icon
278 // Retrieve the controls.
280 _path
= (CEdit
*)GetDlgItem(IDC_PATH
);
281 _thorough
= (CButton
*)GetDlgItem(IDC_THOROUGH
);
282 _remove
= (CButton
*)GetDlgItem(IDC_ORPHAN
);
283 _select
= (CButton
*)GetDlgItem(IDC_SELECTDIR
);
284 _start
= (CButton
*)GetDlgItem(IDC_STARTPATCH
);
285 _cancel
= (CButton
*)GetDlgItem(IDC_CANCELPATCH
);
286 _file
= (CStatic
*)GetDlgItem(IDC_FILE
);
287 _total
= (CStatic
*)GetDlgItem(IDC_TOTAL
);
288 _speed
= (CStatic
*)GetDlgItem(IDC_SPEED
);
289 _status
= (CStatic
*)GetDlgItem(IDC_STATUSBAR
);
290 _percent
= (CStatic
*)GetDlgItem(IDC_PERCENT
);
291 _progress
= (CProgressCtrl
*)GetDlgItem(IDC_PROGRESS
);
294 // Set the patch directory and thorough flag from properties.
296 Ice::PropertiesPtr properties
= _communicator
->getProperties();
297 CString path
= IceUtil::stringToWstring(properties
->getPropertyWithDefault("IcePatch2.Directory", "")).c_str();
298 _path
->SetWindowText(path
);
300 CString thorough
= IceUtil::stringToWstring(properties
->getPropertyWithDefault("IcePatch2.Thorough", "0")).c_str();
301 _thorough
->SetCheck(thorough
!= "0");
303 CString remove
= IceUtil::stringToWstring(properties
->getPropertyWithDefault("IcePatch2.Remove", "0")).c_str();
304 _remove
->SetCheck(remove
!= "0");
307 // Indicate ready status.
311 return TRUE
; // return TRUE unless you set the focus to a control
314 // If you add a minimize button to your dialog, you will need the code below
315 // to draw the icon. For MFC applications using the document/view model,
316 // this is automatically done for you by the framework.
323 CPaintDC
dc(this); // device context for painting
325 SendMessage(WM_ICONERASEBKGND
, reinterpret_cast<WPARAM
>(dc
.GetSafeHdc()), 0);
327 // Center icon in client rectangle
328 int cxIcon
= GetSystemMetrics(SM_CXICON
);
329 int cyIcon
= GetSystemMetrics(SM_CYICON
);
331 GetClientRect(&rect
);
332 int x
= (rect
.Width() - cxIcon
+ 1) / 2;
333 int y
= (rect
.Height() - cyIcon
+ 1) / 2;
336 dc
.DrawIcon(x
, y
, _hIcon
);
344 // The system calls this function to obtain the cursor to display while the user drags
345 // the minimized window.
347 CPatchDlg::OnQueryDragIcon()
349 return static_cast<HCURSOR
>(_hIcon
);
353 CPatchDlg::OnSelectDir()
355 BROWSEINFO info
= { 0 };
356 info
.lpszTitle
= _T("Select Patch Directory");
357 LPITEMIDLIST pidl
= SHBrowseForFolder(&info
);
361 // Get the name of the selected folder.
363 TCHAR path
[MAX_PATH
];
364 if(SHGetPathFromIDList(pidl
, path
))
366 _path
->SetWindowText(path
);
370 // Free up memory used.
372 IMalloc
* imalloc
= 0;
373 if(SUCCEEDED(SHGetMalloc(&imalloc
)))
382 CPatchDlg::OnStartPatch()
386 Ice::PropertiesPtr properties
= _communicator
->getProperties();
389 // Set the patch directory.
392 _path
->GetWindowText(path
);
395 AfxMessageBox(CString(L
"Please select a patch directory."), MB_OK
|MB_ICONEXCLAMATION
);
398 properties
->setProperty("IcePatch2.Directory", IceUtil::wstringToString(wstring(path
)));
401 // Set the thorough patch flag.
403 string thorough
= _thorough
->GetCheck() == BST_CHECKED
? "1" : "0";
404 properties
->setProperty("IcePatch2.Thorough", thorough
);
407 // Set the remove orphan flag.
409 string remove
= _remove
->GetCheck() == BST_CHECKED
? "1" : "0";
410 properties
->setProperty("IcePatch2.Remove", remove
);
412 DialogPatcherFeedbackPtr feedback
= new DialogPatcherFeedback(this);
413 IcePatch2::PatcherPtr patcher
= new IcePatch2::Patcher(_communicator
, feedback
);
416 // Disable a few controls during the patch process.
418 _path
->EnableWindow(false);
419 _select
->EnableWindow(false);
420 _thorough
->EnableWindow(false);
421 _remove
->EnableWindow(false);
422 _start
->EnableWindow(false);
427 bool aborted
= !patcher
->prepare();
430 aborted
= !patcher
->patch("");
438 // Reset and indicate the completion status.
440 reset(aborted
? L
" Aborted" : L
" Completed");
442 catch(const IceUtil::Exception
& ex
)
446 catch(const string
& ex
)
448 AfxMessageBox(CString(ex
.c_str()), MB_OK
|MB_ICONEXCLAMATION
);
453 CPatchDlg::OnCancel()
456 _status
->SetWindowText(CString(L
" Canceled"));
461 CPatchDlg::reset(const CString
& status
)
465 _path
->EnableWindow(true);
466 _select
->EnableWindow(true);
467 _thorough
->EnableWindow(true);
468 _remove
->EnableWindow(true);
469 _start
->EnableWindow(true);
471 _status
->SetWindowText(status
);
472 _file
->SetWindowText(CString());
473 _total
->SetWindowText(CString());
474 _speed
->SetWindowText(CString());
475 _percent
->SetWindowText(CString());
477 _progress
->SetPos(0);
481 CPatchDlg::processMessages()
484 while(::PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
))
486 TranslateMessage(&msg
);
487 DispatchMessage(&msg
);
492 CPatchDlg::handleException(const IceUtil::Exception
& e
)
498 catch(const IceUtil::Exception
& ex
)
502 string s
= ostr
.str();
503 AfxMessageBox(CString(s
.c_str()), MB_OK
|MB_ICONEXCLAMATION
);
510 CPatchDlg::convertSize(Ice::Long size
) const
513 double start
= static_cast<double>(size
);
514 double final
= start
/ gigabyte
;
521 final
= start
/ megabyte
;
528 final
= start
/ kilobyte
;
542 convert
.Format(L
"%.1f %s", final
, units
);