FileOperationProgress.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "FileOperationProgress.h"
  6. //---------------------------------------------------------------------------
  7. #define TRANSFER_BUF_SIZE 4096
  8. //---------------------------------------------------------------------------
  9. __fastcall TFileOperationProgressType::TFileOperationProgressType()
  10. {
  11. FOnProgress = NULL;
  12. FOnFinished = NULL;
  13. Clear();
  14. }
  15. //---------------------------------------------------------------------------
  16. __fastcall TFileOperationProgressType::TFileOperationProgressType(
  17. TFileOperationProgressEvent AOnProgress, TFileOperationFinished AOnFinished)
  18. {
  19. FOnProgress = AOnProgress;
  20. FOnFinished = AOnFinished;
  21. FReset = false;
  22. Clear();
  23. }
  24. //---------------------------------------------------------------------------
  25. __fastcall TFileOperationProgressType::~TFileOperationProgressType()
  26. {
  27. assert((!InProgress && !Suspended) || FReset);
  28. }
  29. //---------------------------------------------------------------------------
  30. void __fastcall TFileOperationProgressType::Clear()
  31. {
  32. FileName = "";
  33. AsciiTransfer = false;
  34. ResumeStatus = rsNotAvailable;
  35. Count = 0;
  36. FFilesFinished = 0;
  37. StartTime = Now();
  38. FStopped = 0;
  39. Suspended = false;
  40. FSuspendTime = 0;
  41. InProgress = false;
  42. TotalTransfered = 0;
  43. TotalSkipped = 0;
  44. TotalSize = 0;
  45. SkippedSize = 0;
  46. TotalSizeSet = false;
  47. Operation = foNone;
  48. Temp = false;
  49. YesToAll = false;
  50. YesToNewer = false;
  51. NoToAll = false;
  52. SkipToAll = false;
  53. AlternateResumeAlways = false;
  54. // to bypass check in ClearTransfer()
  55. TransferSize = 0;
  56. ClearTransfer();
  57. }
  58. //---------------------------------------------------------------------------
  59. void __fastcall TFileOperationProgressType::ClearTransfer()
  60. {
  61. if ((TransferSize > 0) && (TransferedSize < TransferSize))
  62. {
  63. __int64 RemainingSize = (TransferSize - TransferedSize);
  64. TotalSkipped += RemainingSize;
  65. }
  66. LocalSize = 0;
  67. TransferSize = 0;
  68. LocalyUsed = 0;
  69. SkippedSize = 0;
  70. TransferedSize = 0;
  71. TransferingFile = false;
  72. FFileStopped = 0;
  73. }
  74. //---------------------------------------------------------------------------
  75. void __fastcall TFileOperationProgressType::Start(TFileOperation AOperation,
  76. TOperationSide ASide, int ACount, bool ATemp,
  77. const AnsiString ADirectory)
  78. {
  79. Clear();
  80. Operation = AOperation;
  81. Side = ASide;
  82. Count = ACount;
  83. InProgress = true;
  84. Cancel = csContinue;
  85. Directory = ADirectory;
  86. Temp = ATemp;
  87. DoProgress();
  88. }
  89. //---------------------------------------------------------------------------
  90. void __fastcall TFileOperationProgressType::Reset()
  91. {
  92. FReset = true;
  93. }
  94. //---------------------------------------------------------------------------
  95. void __fastcall TFileOperationProgressType::Stop()
  96. {
  97. // added to include remaining bytes to TotalSkipped, in case
  98. // the progress happes to update before closing
  99. ClearTransfer();
  100. InProgress = false;
  101. DoProgress();
  102. }
  103. //---------------------------------------------------------------------------
  104. void __fastcall TFileOperationProgressType::Suspend()
  105. {
  106. assert(!Suspended);
  107. Suspended = true;
  108. FSuspendTime = Now();
  109. DoProgress();
  110. }
  111. //---------------------------------------------------------------------------
  112. void __fastcall TFileOperationProgressType::Resume()
  113. {
  114. assert(Suspended);
  115. Suspended = false;
  116. TDateTime TimeSuspended = (Now() - FSuspendTime);
  117. // see CPS()
  118. FStopped += TimeSuspended;
  119. FFileStopped += TimeSuspended;
  120. DoProgress();
  121. }
  122. //---------------------------------------------------------------------------
  123. int __fastcall TFileOperationProgressType::OperationProgress()
  124. {
  125. assert(Count);
  126. return (FFilesFinished * 100)/Count;
  127. }
  128. //---------------------------------------------------------------------------
  129. int __fastcall TFileOperationProgressType::TransferProgress()
  130. {
  131. if (TransferSize) return (int)((TransferedSize * 100)/TransferSize);
  132. else return 0;
  133. }
  134. //---------------------------------------------------------------------------
  135. int __fastcall TFileOperationProgressType::TotalTransferProgress()
  136. {
  137. assert(TotalSizeSet);
  138. int Result = TotalSize > 0 ? (int)(((TotalTransfered + TotalSkipped) * 100)/TotalSize) : 0;
  139. return Result < 100 ? Result : 100;
  140. }
  141. //---------------------------------------------------------------------------
  142. int __fastcall TFileOperationProgressType::OverallProgress()
  143. {
  144. if (TotalSizeSet)
  145. {
  146. assert((Operation == foCopy) || (Operation == foMove));
  147. return TotalTransferProgress();
  148. }
  149. else
  150. {
  151. return OperationProgress();
  152. }
  153. }
  154. //---------------------------------------------------------------------------
  155. void __fastcall TFileOperationProgressType::DoProgress()
  156. {
  157. if (FOnProgress) FOnProgress(*this, Cancel);
  158. }
  159. //---------------------------------------------------------------------------
  160. void __fastcall TFileOperationProgressType::Finish(AnsiString FileName,
  161. bool Success, bool & DisconnectWhenComplete)
  162. {
  163. assert(InProgress);
  164. if (FOnFinished)
  165. {
  166. FOnFinished(Operation, Side, Temp, FileName,
  167. /* TODO : There wasn't 'Success' condition, was it by mistake or by purpose? */
  168. Success && (Cancel == csContinue), DisconnectWhenComplete);
  169. }
  170. FFilesFinished++;
  171. DoProgress();
  172. }
  173. //---------------------------------------------------------------------------
  174. void __fastcall TFileOperationProgressType::SetFile(AnsiString AFileName)
  175. {
  176. FileName = AFileName;
  177. ClearTransfer();
  178. FFileStartTime = Now();
  179. DoProgress();
  180. }
  181. //---------------------------------------------------------------------------
  182. void __fastcall TFileOperationProgressType::SetLocalSize(__int64 ASize)
  183. {
  184. LocalSize = ASize;
  185. DoProgress();
  186. }
  187. //---------------------------------------------------------------------------
  188. void __fastcall TFileOperationProgressType::AddLocalyUsed(__int64 ASize)
  189. {
  190. LocalyUsed += ASize;
  191. if (LocalyUsed > LocalSize)
  192. {
  193. LocalSize = LocalyUsed;
  194. }
  195. DoProgress();
  196. }
  197. //---------------------------------------------------------------------------
  198. bool __fastcall TFileOperationProgressType::IsLocalyDone()
  199. {
  200. assert(LocalyUsed <= LocalSize);
  201. return (LocalyUsed == LocalSize);
  202. }
  203. //---------------------------------------------------------------------------
  204. unsigned long __fastcall TFileOperationProgressType::LocalBlockSize()
  205. {
  206. unsigned long Result = TRANSFER_BUF_SIZE;
  207. if (LocalyUsed + Result > LocalSize) Result = (unsigned long)(LocalSize - LocalyUsed);
  208. return Result;
  209. }
  210. //---------------------------------------------------------------------------
  211. void __fastcall TFileOperationProgressType::SetTotalSize(__int64 ASize)
  212. {
  213. TotalSize = ASize;
  214. TotalSizeSet = true;
  215. DoProgress();
  216. }
  217. //---------------------------------------------------------------------------
  218. void __fastcall TFileOperationProgressType::SetTransferSize(__int64 ASize)
  219. {
  220. TransferSize = ASize;
  221. DoProgress();
  222. }
  223. //---------------------------------------------------------------------------
  224. void __fastcall TFileOperationProgressType::ChangeTransferSize(__int64 ASize)
  225. {
  226. // reflect change on file size (due to text transfer mode conversion particulary)
  227. // on total transfer size
  228. if (TotalSizeSet)
  229. {
  230. TotalSize += (ASize - TransferSize);
  231. }
  232. TransferSize = ASize;
  233. DoProgress();
  234. }
  235. //---------------------------------------------------------------------------
  236. void __fastcall TFileOperationProgressType::RollbackTransfer()
  237. {
  238. TransferedSize -= SkippedSize;
  239. assert(TransferedSize <= TotalTransfered);
  240. TotalTransfered -= TransferedSize;
  241. assert(SkippedSize <= TotalSkipped);
  242. TotalSkipped -= SkippedSize;
  243. SkippedSize = 0;
  244. TransferedSize = 0;
  245. TransferSize = 0;
  246. LocalyUsed = 0;
  247. }
  248. //---------------------------------------------------------------------------
  249. void __fastcall TFileOperationProgressType::AddTransfered(__int64 ASize,
  250. bool AddToTotals)
  251. {
  252. TransferedSize += ASize;
  253. if (TransferedSize > TransferSize)
  254. {
  255. // this can happen with SFTP when downloading file that
  256. // grows while being downloaded
  257. if (TotalSizeSet)
  258. {
  259. TotalSize += (TransferedSize - TransferSize);
  260. }
  261. TransferSize = TransferedSize;
  262. }
  263. if (AddToTotals)
  264. {
  265. TotalTransfered += ASize;
  266. }
  267. DoProgress();
  268. }
  269. //---------------------------------------------------------------------------
  270. void __fastcall TFileOperationProgressType::AddResumed(__int64 ASize)
  271. {
  272. TotalSkipped += ASize;
  273. SkippedSize += ASize;
  274. AddTransfered(ASize, false);
  275. AddLocalyUsed(ASize);
  276. }
  277. //---------------------------------------------------------------------------
  278. unsigned long __fastcall TFileOperationProgressType::TransferBlockSize()
  279. {
  280. unsigned long Result = TRANSFER_BUF_SIZE;
  281. if (TransferedSize + Result > TransferSize) Result = (unsigned long)(TransferSize - TransferedSize);
  282. return Result;
  283. }
  284. //---------------------------------------------------------------------------
  285. unsigned long __fastcall TFileOperationProgressType::StaticBlockSize()
  286. {
  287. return TRANSFER_BUF_SIZE;
  288. }
  289. //---------------------------------------------------------------------------
  290. bool __fastcall TFileOperationProgressType::IsTransferDone()
  291. {
  292. assert(TransferedSize <= TransferSize);
  293. return (TransferedSize == TransferSize);
  294. }
  295. //---------------------------------------------------------------------------
  296. void __fastcall TFileOperationProgressType::SetAsciiTransfer(bool AAsciiTransfer)
  297. {
  298. AsciiTransfer = AAsciiTransfer;
  299. DoProgress();
  300. }
  301. //---------------------------------------------------------------------------
  302. void __fastcall TFileOperationProgressType::SetResumeStatus(TResumeStatus AResumeStatus)
  303. {
  304. ResumeStatus = AResumeStatus;
  305. DoProgress();
  306. }
  307. //---------------------------------------------------------------------------
  308. TDateTime __fastcall TFileOperationProgressType::TimeElapsed()
  309. {
  310. return Now() - StartTime;
  311. }
  312. //---------------------------------------------------------------------------
  313. unsigned int __fastcall TFileOperationProgressType::CPS()
  314. {
  315. TDateTime CurTime = Suspended ? FSuspendTime : Now();
  316. TDateTime RealTime = (CurTime - StartTime) - FStopped;
  317. if ((double)RealTime > 0)
  318. {
  319. return TotalTransfered / ((double)RealTime * (24 * 60 * 60));
  320. }
  321. else
  322. {
  323. return 0;
  324. }
  325. }
  326. //---------------------------------------------------------------------------
  327. TDateTime __fastcall TFileOperationProgressType::TimeExpected()
  328. {
  329. unsigned int CurCps = CPS();
  330. if (CurCps) return TDateTime((double)(((double)(TransferSize - TransferedSize)) / CurCps) / (24 * 60 * 60));
  331. else return 0;
  332. }
  333. //---------------------------------------------------------------------------
  334. TDateTime __fastcall TFileOperationProgressType::TotalTimeExpected()
  335. {
  336. assert(TotalSizeSet);
  337. unsigned int CurCps = CPS();
  338. // sanity check
  339. if ((CurCps > 0) && (TotalSize > TotalSkipped))
  340. {
  341. return TDateTime((double)((double)(TotalSize - TotalSkipped) / CurCps) /
  342. (24 * 60 * 60));
  343. }
  344. else
  345. {
  346. return 0;
  347. }
  348. }
  349. //---------------------------------------------------------------------------
  350. TDateTime __fastcall TFileOperationProgressType::TotalTimeLeft()
  351. {
  352. assert(TotalSizeSet);
  353. unsigned int CurCps = CPS();
  354. // sanity check
  355. if ((CurCps > 0) && (TotalSize > TotalSkipped + TotalTransfered))
  356. {
  357. return TDateTime((double)((double)(TotalSize - TotalSkipped - TotalTransfered) / CurCps) /
  358. (24 * 60 * 60));
  359. }
  360. else
  361. {
  362. return 0;
  363. }
  364. }