1
0

Progress.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. //---------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include <CoreMain.h>
  6. #include <TextsWin.h>
  7. #include <HelpWin.h>
  8. #include <WinInterface.h>
  9. #include <VCLCommon.h>
  10. #include <CustomWinConfiguration.h>
  11. #include <GUITools.h>
  12. #include <BaseUtils.hpp>
  13. #include <DateUtils.hpp>
  14. #include <Consts.hpp>
  15. #include <HistoryComboBox.hpp>
  16. #include "Progress.h"
  17. //---------------------------------------------------------------------
  18. #pragma link "PathLabel"
  19. #pragma link "PngImageList"
  20. #pragma link "TB2Dock"
  21. #pragma link "TB2Item"
  22. #pragma link "TB2Toolbar"
  23. #pragma link "TBX"
  24. #pragma link "TB2ExtItems"
  25. #pragma link "TBXExtItems"
  26. #ifndef NO_RESOURCES
  27. #pragma resource "*.dfm"
  28. #endif
  29. //---------------------------------------------------------------------
  30. UnicodeString __fastcall TProgressForm::ProgressStr(
  31. const TSynchronizeProgress * SynchronizeProgress, const TFileOperationProgressType * ProgressData)
  32. {
  33. static const int Captions[] = { 0, 0, PROGRESS_DELETE,
  34. PROGRESS_SETPROPERTIES, 0, PROGRESS_CUSTOM_COMAND, PROGRESS_CALCULATE_SIZE,
  35. PROGRESS_REMOTE_MOVE, PROGRESS_REMOTE_COPY, PROGRESS_GETPROPERTIES,
  36. PROGRESS_CALCULATE_CHECKSUM, PROGRESS_LOCK, PROGRESS_UNLOCK };
  37. DebugAssert((unsigned int)ProgressData->Operation >= 1 && ((unsigned int)ProgressData->Operation - 1) < LENOF(Captions));
  38. int Id;
  39. if ((ProgressData->Operation == foCopy) || (ProgressData->Operation == foMove))
  40. {
  41. Id = (ProgressData->Side == osLocal) ? PROGRESS_UPLOAD : PROGRESS_DOWNLOAD;
  42. }
  43. else
  44. {
  45. Id = Captions[(int)ProgressData->Operation - 1];
  46. DebugAssert(Id != 0);
  47. }
  48. UnicodeString Result = LoadStr(Id);
  49. if (SynchronizeProgress != NULL)
  50. {
  51. Result = FORMAT(L"%s - %s", (LoadStr(SYNCHRONIZE_PROGRESS_SYNCHRONIZE2), Result));
  52. }
  53. if (!TFileOperationProgressType::IsIndeterminateOperation(ProgressData->Operation))
  54. {
  55. int OverallProgress;
  56. if (SynchronizeProgress != NULL)
  57. {
  58. OverallProgress = SynchronizeProgress->Progress(ProgressData);
  59. }
  60. else
  61. {
  62. OverallProgress = ProgressData->OverallProgress();
  63. }
  64. Result = FORMAT(L"%d%% %s", (OverallProgress, Result));
  65. }
  66. return Result;
  67. }
  68. //---------------------------------------------------------------------
  69. __fastcall TProgressForm::TProgressForm(
  70. TComponent * AOwner, bool AllowMoveToQueue, bool AllowSkip, TSynchronizeProgress * SynchronizeProgress)
  71. : FData(), TForm(AOwner)
  72. {
  73. FLastOperation = foNone;
  74. FLastSide = (TOperationSide)-1;
  75. FLastTotalSizeSet = false;
  76. FDataGot = false;
  77. FDataReceived = false;
  78. FCancel = csContinue;
  79. FMoveToQueue = false;
  80. FMinimizedByMe = false;
  81. FUpdateCounter = 0;
  82. FDeleteLocalToRecycleBin = false;
  83. FDeleteRemoteToRecycleBin = false;
  84. FReadOnly = false;
  85. FShowAsModalStorage = NULL;
  86. FStarted = Now();
  87. FModalBeginHooked = false;
  88. FModalLevel = -1;
  89. FPendingSkip = false;
  90. FSynchronizeProgress = SynchronizeProgress;
  91. FAllowSkip = AllowSkip;
  92. UseSystemSettings(this);
  93. FOnceDoneItems.Add(odoIdle, IdleOnceDoneItem);
  94. FOnceDoneItems.Add(odoDisconnect, DisconnectOnceDoneItem);
  95. FOnceDoneItems.Add(odoSuspend, SuspendOnceDoneItem);
  96. FOnceDoneItems.Add(odoShutDown, ShutDownOnceDoneItem);
  97. ResetOnceDoneOperation();
  98. HideComponentsPanel(this);
  99. SelectScaledImageList(ImageList);
  100. SetGlobalMinimizeHandler(this, GlobalMinimize);
  101. MoveToQueueItem->Visible = AllowMoveToQueue;
  102. }
  103. //---------------------------------------------------------------------------
  104. __fastcall TProgressForm::~TProgressForm()
  105. {
  106. // to prevent raising assertion (e.g. IsProgress == True)
  107. FData.Clear();
  108. ClearGlobalMinimizeHandler(GlobalMinimize);
  109. if (IsApplicationMinimized() && FMinimizedByMe)
  110. {
  111. ShowNotification(
  112. NULL, MainInstructions(LoadStr(BALLOON_OPERATION_COMPLETE)),
  113. qtInformation);
  114. }
  115. ReleaseAsModal(this, FShowAsModalStorage);
  116. }
  117. //---------------------------------------------------------------------
  118. UnicodeString __fastcall TProgressForm::ProgressStr()
  119. {
  120. return FProgressStr;
  121. }
  122. //---------------------------------------------------------------------
  123. void __fastcall TProgressForm::UpdateControls()
  124. {
  125. DebugAssert((FData.Operation >= foCopy) && (FData.Operation <= foUnlock) &&
  126. (FData.Operation != foRename));
  127. bool TransferOperation =
  128. ((FData.Operation == foCopy) || (FData.Operation == foMove));
  129. CancelItem->Enabled = !FReadOnly && (FCancel < csCancel);
  130. SkipItem->Visible = TransferOperation && FAllowSkip;
  131. SkipItem->Enabled = !FReadOnly && (FCancel < csCancelFile) && !FPendingSkip;
  132. MoveToQueueItem->Enabled = !FMoveToQueue && (FCancel == csContinue) && !FPendingSkip;
  133. CycleOnceDoneItem->Visible =
  134. !FReadOnly &&
  135. (FData.Operation != foCalculateSize) &&
  136. (FData.Operation != foGetProperties) &&
  137. (FData.Operation != foCalculateChecksum);
  138. CycleOnceDoneItem->ImageIndex = CurrentOnceDoneItem()->ImageIndex;
  139. SpeedComboBoxItem->Visible = TransferOperation;
  140. if ((FData.Operation != FLastOperation) ||
  141. (FData.Side != FLastSide))
  142. {
  143. UnicodeString Animation;
  144. UnicodeString CancelCaption = Vcl_Consts_SMsgDlgCancel;
  145. int MoveToQueueImageIndex = -1;
  146. FPendingSkip = false; // just in case
  147. int MoveTransferToQueueImageIndex;
  148. if (FData.Side == osRemote)
  149. {
  150. MoveTransferToQueueImageIndex = 7;
  151. }
  152. else
  153. {
  154. MoveTransferToQueueImageIndex = 8;
  155. }
  156. switch (FData.Operation)
  157. {
  158. case foCopy:
  159. if (FData.Side == osRemote)
  160. {
  161. Animation = L"CopyRemote";
  162. }
  163. else
  164. {
  165. Animation = L"CopyLocal";
  166. }
  167. MoveToQueueImageIndex = MoveTransferToQueueImageIndex;
  168. break;
  169. case foMove:
  170. if (FData.Side == osRemote)
  171. {
  172. Animation = L"MoveRemote";
  173. }
  174. else
  175. {
  176. Animation = L"MoveLocal";
  177. }
  178. MoveToQueueImageIndex = MoveTransferToQueueImageIndex;
  179. break;
  180. case foDelete:
  181. Animation = ((FData.Side == osRemote) ? DeleteRemoteToRecycleBin : DeleteLocalToRecycleBin) ? L"Recycle" : L"Delete";
  182. break;
  183. case foCalculateSize:
  184. Animation = L"CalculateSize";
  185. CancelCaption = LoadStr(SKIP_BUTTON);
  186. MoveToQueueImageIndex = MoveTransferToQueueImageIndex;
  187. break;
  188. case foSetProperties:
  189. Animation = "SetProperties";
  190. break;
  191. default:
  192. DebugAssert(
  193. (FData.Operation == foCustomCommand) ||
  194. (FData.Operation == foGetProperties) ||
  195. (FData.Operation == foCalculateChecksum) ||
  196. (FData.Operation == foLock) ||
  197. (FData.Operation == foUnlock) ||
  198. (FData.Operation == foRemoteCopy) ||
  199. (FData.Operation == foRemoteMove));
  200. break;
  201. }
  202. CancelItem->Caption = CancelCaption;
  203. OperationProgress->Style = TFileOperationProgressType::IsIndeterminateOperation(FData.Operation) ? pbstMarquee : pbstNormal;
  204. if (SynchronizeProgress != NULL)
  205. {
  206. Animation = L"SynchronizeDirectories";
  207. }
  208. FFrameAnimation.Init(AnimationPaintBox, Animation);
  209. FFrameAnimation.Start();
  210. int Delta = 0;
  211. if (TransferOperation && !TransferPanel->Visible) Delta += TransferPanel->Height;
  212. else
  213. if (!TransferOperation && TransferPanel->Visible) Delta += -TransferPanel->Height;
  214. TransferPanel->Visible = TransferOperation;
  215. ClientHeight = ClientHeight + Delta;
  216. TargetLabel->Visible = TransferOperation;
  217. TargetPathLabel->Visible = TransferOperation;
  218. TargetPathLabel->UnixPath = (FData.Side == osLocal);
  219. FileLabel->UnixPath = (FData.Side == osRemote);
  220. PathLabel->Caption =
  221. LoadStr((FData.Operation == foCalculateSize) ? PROGRESS_PATH_LABEL : PROGRESS_FILE_LABEL);
  222. MoveToQueueItem->ImageIndex = MoveToQueueImageIndex;
  223. FLastOperation = FData.Operation;
  224. FLastSide = FData.Side;
  225. FLastTotalSizeSet = !FData.TotalSizeSet;
  226. }
  227. if (FLastTotalSizeSet != FData.TotalSizeSet)
  228. {
  229. StartTimeLabelLabel->Visible = !FData.TotalSizeSet;
  230. StartTimeLabel->Visible = !FData.TotalSizeSet;
  231. TimeLeftLabelLabel->Visible = FData.TotalSizeSet;
  232. TimeLeftLabel->Visible = FData.TotalSizeSet;
  233. FLastTotalSizeSet = FData.TotalSizeSet;
  234. }
  235. UnicodeString FileCaption;
  236. if ((FData.Operation == foCalculateSize) && DebugAlwaysTrue(!FData.Temp))
  237. {
  238. if (FData.Side == osRemote)
  239. {
  240. FileCaption = UnixExtractFileDir(FData.FullFileName);
  241. }
  242. else
  243. {
  244. FileCaption = ExtractFileDir(FData.FullFileName);
  245. }
  246. }
  247. else if ((FData.Side == osRemote) || !FData.Temp)
  248. {
  249. FileCaption = FData.FileName;
  250. }
  251. else
  252. {
  253. FileCaption = ExtractFileName(FData.FileName);
  254. }
  255. if (FileLabel->Caption != FileCaption)
  256. {
  257. FileLabel->Caption = FileCaption;
  258. FPendingSkip = false;
  259. }
  260. int OverallProgress;
  261. // as a side effect this prevents calling TSynchronizeProgress::Progress when we do not know total size yet
  262. // (what would cache wrong values forever)
  263. if (TFileOperationProgressType::IsIndeterminateOperation(FData.Operation))
  264. {
  265. OverallProgress = -1;
  266. }
  267. else
  268. {
  269. if (SynchronizeProgress != NULL)
  270. {
  271. OverallProgress = SynchronizeProgress->Progress(&FData);
  272. }
  273. else
  274. {
  275. OverallProgress = FData.OverallProgress();
  276. }
  277. }
  278. OperationProgress->Position = std::max(0, OverallProgress);
  279. OperationProgress->Hint = (OverallProgress < 0) ? UnicodeString() : FORMAT(L"%d%%", (OverallProgress));
  280. FProgressStr = ProgressStr(SynchronizeProgress, &FData);
  281. Caption = FormatFormCaption(this, FProgressStr);
  282. if (TransferOperation)
  283. {
  284. if ((FData.Side == osLocal) || !FData.Temp)
  285. {
  286. TargetPathLabel->Caption = FData.Directory;
  287. }
  288. else
  289. {
  290. TargetPathLabel->Caption = LoadStr(PROGRESS_TEMP_DIR);
  291. }
  292. StartTimeLabel->Caption = FData.StartTime.TimeString();
  293. if (FData.TotalSizeSet)
  294. {
  295. TDateTime TimeLeft;
  296. if (SynchronizeProgress != NULL)
  297. {
  298. TimeLeft = SynchronizeProgress->TimeLeft(&FData);
  299. }
  300. else
  301. {
  302. TimeLeft = FData.TotalTimeLeft();
  303. }
  304. TimeLeftLabel->Caption = FormatDateTimeSpan(Configuration->TimeFormat, TimeLeft);
  305. }
  306. TimeElapsedLabel->Caption = FormatDateTimeSpan(Configuration->TimeFormat, FData.TimeElapsed());
  307. BytesTransferredLabel->Caption = FormatBytes(FData.TotalTransferred);
  308. CPSLabel->Caption = FORMAT(L"%s/s", (FormatBytes(FData.CPS())));
  309. FileProgress->Position = FData.TransferProgress();
  310. FileProgress->Hint = FORMAT(L"%d%%", (FileProgress->Position));
  311. }
  312. }
  313. //---------------------------------------------------------------------
  314. static __int64 DelayStartInterval = MSecsPerSec / 2;
  315. static __int64 UpdateInterval = 1 * MSecsPerSec;
  316. //---------------------------------------------------------------------
  317. bool __fastcall TProgressForm::ReceiveData(bool Force, int ModalLevelOffset)
  318. {
  319. bool Result = false;
  320. if (FDataGot && !FDataReceived)
  321. {
  322. // CPS limit is set set only once from TFileOperationProgressType::Start.
  323. // Needs to be set even when data are not accepted yet, otherwise we would
  324. // write default value to FData in TProgressForm::SetProgressData
  325. FCPSLimit = FData.CPSLimit;
  326. // Never popup over dialog that appeared later than we started
  327. // (this can happen from UpdateTimerTimer when application is
  328. // restored while overwrite confirmation dialog [or any other]
  329. // is already shown).
  330. // TODO We should probably take as-modal windows into account too
  331. // (for extreme cases like restoring while reconnecting [as-modal TAuthenticateForm]).
  332. if ((FModalLevel < 0) || (Application->ModalLevel + ModalLevelOffset <= FModalLevel))
  333. {
  334. // Delay showing the progress until the application is restored,
  335. // otherwise the form popups up unminimized.
  336. // See solution in TMessageForm::CMShowingChanged.
  337. if (!IsApplicationMinimized() &&
  338. (Force || (MilliSecondsBetween(Now(), FStarted) > DelayStartInterval)))
  339. {
  340. FDataReceived = true;
  341. SpeedComboBoxItem->Text = SetSpeedLimit(FCPSLimit);
  342. ShowAsModal(this, FShowAsModalStorage);
  343. // particularly needed for the case, when we are showing the form delayed
  344. // because application was minimized when operation started
  345. Result = true;
  346. }
  347. else if (!FModalBeginHooked && DebugAlwaysTrue(FModalLevel < 0))
  348. {
  349. // record state as of time, the window should be shown,
  350. // had not we implemented delayed show
  351. ApplicationEvents->OnModalBegin = ApplicationModalBegin;
  352. FModalBeginHooked = true;
  353. FModalLevel = Application->ModalLevel;
  354. }
  355. }
  356. }
  357. return Result;
  358. }
  359. //---------------------------------------------------------------------------
  360. void __fastcall TProgressForm::ApplicationModalBegin(TObject * /*Sender*/)
  361. {
  362. // Popup before any modal dialog shows (typically overwrite confirmation,
  363. // as that popups nearly instantly, i.e. less than DelayStartInterval).
  364. // The Application->ModalLevel is already incremented, but we should treat it as
  365. // if it were not as the dialog is not created yet (so we can popup if we are not yet).
  366. ReceiveData(true, -1);
  367. }
  368. //---------------------------------------------------------------------
  369. void __fastcall TProgressForm::SetProgressData(TFileOperationProgressType & AData)
  370. {
  371. bool InstantUpdate = false;
  372. // workaround: to force displaing first file data immediately,
  373. // otherwise form dialog uses to be blank for first second
  374. // (until UpdateTimerTimer)
  375. if (FileLabel->Caption.IsEmpty() && !AData.FileName.IsEmpty())
  376. {
  377. InstantUpdate = true;
  378. }
  379. FData.AssignButKeepSuspendState(AData);
  380. FDataGot = true;
  381. if (!UpdateTimer->Enabled)
  382. {
  383. UpdateTimer->Interval = static_cast<int>(DelayStartInterval);
  384. UpdateTimer->Enabled = true;
  385. FSinceLastUpdate = 0;
  386. }
  387. if (ReceiveData(false, 0))
  388. {
  389. InstantUpdate = true;
  390. }
  391. if (InstantUpdate)
  392. {
  393. UpdateControls();
  394. Application->ProcessMessages();
  395. }
  396. if (ProcessGUI(FUpdateCounter % 5 == 0))
  397. {
  398. FUpdateCounter = 0;
  399. }
  400. FUpdateCounter++;
  401. AData.SetCPSLimit(FCPSLimit);
  402. }
  403. //---------------------------------------------------------------------------
  404. void __fastcall TProgressForm::UpdateTimerTimer(TObject * /*Sender*/)
  405. {
  406. // popup the progress window at least here, if SetProgressData is
  407. // not being called (typically this happens when using custom command
  408. // that launches long-lasting external process, such as visual diff)
  409. ReceiveData(false, 0);
  410. if (UpdateTimer->Interval == DelayStartInterval)
  411. {
  412. UpdateTimer->Interval = static_cast<int>(GUIUpdateInterval);
  413. }
  414. if (FDataReceived)
  415. {
  416. FSinceLastUpdate += UpdateTimer->Interval;
  417. if (FSinceLastUpdate >= UpdateInterval)
  418. {
  419. UpdateControls();
  420. FSinceLastUpdate = 0;
  421. }
  422. }
  423. }
  424. //---------------------------------------------------------------------------
  425. void __fastcall TProgressForm::FormShow(TObject * /*Sender*/)
  426. {
  427. CopySpeedLimits(CustomWinConfiguration->History[L"SpeedLimit"], SpeedComboBoxItem->Strings);
  428. ReceiveData(false, 0);
  429. if (FDataReceived)
  430. {
  431. UpdateControls();
  432. }
  433. // HACK: In command-line run (/upload), FormShow gets called twice,
  434. // leading to duplicate hook and memory leak. Make sure we unhook, just in case.
  435. // Calling unhook without hooking first is noop.
  436. UnhookFormActivation(this);
  437. HookFormActivation(this);
  438. }
  439. //---------------------------------------------------------------------------
  440. void __fastcall TProgressForm::FormHide(TObject * /*Sender*/)
  441. {
  442. UnhookFormActivation(this);
  443. // This is to counter the "infinite" timestamp in
  444. // TTerminalManager::ApplicationShowHint.
  445. // Because if form disappears on its own, hint is not hidden.
  446. Application->CancelHint();
  447. CustomWinConfiguration->History[L"SpeedLimit"] = SpeedComboBoxItem->Strings;
  448. UpdateTimer->Enabled = false;
  449. }
  450. //---------------------------------------------------------------------------
  451. void __fastcall TProgressForm::CancelItemClick(TObject * /*Sender*/)
  452. {
  453. CancelOperation();
  454. }
  455. //---------------------------------------------------------------------------
  456. void __fastcall TProgressForm::Minimize(TObject * Sender)
  457. {
  458. CallGlobalMinimizeHandler(Sender);
  459. }
  460. //---------------------------------------------------------------------------
  461. void __fastcall TProgressForm::MinimizeItemClick(TObject * Sender)
  462. {
  463. Minimize(Sender);
  464. }
  465. //---------------------------------------------------------------------------
  466. void __fastcall TProgressForm::CancelOperation()
  467. {
  468. DebugAssert(FDataReceived);
  469. if (!FData.Suspended)
  470. {
  471. // mostly useless, as suspend is called over copy of actual progress data
  472. FData.Suspend();
  473. UpdateControls();
  474. try
  475. {
  476. TCancelStatus ACancel;
  477. if (FData.TransferringFile &&
  478. (FData.TimeExpected() > GUIConfiguration->IgnoreCancelBeforeFinish))
  479. {
  480. int Result = MessageDialog(LoadStr(CANCEL_OPERATION_FATAL2), qtWarning,
  481. qaYes | qaNo | qaCancel, HELP_PROGRESS_CANCEL);
  482. switch (Result)
  483. {
  484. case qaYes:
  485. ACancel = csCancelTransfer; break;
  486. case qaNo:
  487. ACancel = csCancel; break;
  488. default:
  489. ACancel = csContinue; break;
  490. }
  491. }
  492. else
  493. {
  494. ACancel = csCancel;
  495. }
  496. SetCancelLower(ACancel);
  497. }
  498. __finally
  499. {
  500. FData.Resume();
  501. }
  502. }
  503. }
  504. //---------------------------------------------------------------------------
  505. void __fastcall TProgressForm::GlobalMinimize(TObject * /*Sender*/)
  506. {
  507. ApplicationMinimize();
  508. FMinimizedByMe = true;
  509. }
  510. //---------------------------------------------------------------------------
  511. TTBCustomItem * __fastcall TProgressForm::CurrentOnceDoneItem()
  512. {
  513. TOnceDoneItems::const_iterator Iterator = FOnceDoneItems.begin();
  514. while (Iterator != FOnceDoneItems.end())
  515. {
  516. if (Iterator->second->Checked)
  517. {
  518. return Iterator->second;
  519. }
  520. Iterator++;
  521. }
  522. DebugFail();
  523. return NULL;
  524. }
  525. //---------------------------------------------------------------------------
  526. TOnceDoneOperation __fastcall TProgressForm::GetOnceDoneOperation()
  527. {
  528. return FOnceDoneItems.LookupFirst(CurrentOnceDoneItem());
  529. }
  530. //---------------------------------------------------------------------------
  531. void __fastcall TProgressForm::SetOnceDoneItem(TTBCustomItem * Item)
  532. {
  533. TTBCustomItem * Current = CurrentOnceDoneItem();
  534. if (Current != Item)
  535. {
  536. Current->Checked = false;
  537. Item->Checked = true;
  538. // Not until we have any data to update.
  539. // Happens when set to odoDisconnect in command-line upload/download
  540. // mode from TCustomScpExplorerForm::FileOperationProgress.
  541. if (FDataGot)
  542. {
  543. UpdateControls();
  544. }
  545. }
  546. }
  547. //---------------------------------------------------------------------------
  548. void __fastcall TProgressForm::SetOnceDoneOperation(TOnceDoneOperation value)
  549. {
  550. SetOnceDoneItem(FOnceDoneItems.LookupSecond(value));
  551. }
  552. //---------------------------------------------------------------------------
  553. bool __fastcall TProgressForm::GetAllowMinimize()
  554. {
  555. return MinimizeItem->Visible;
  556. }
  557. //---------------------------------------------------------------------------
  558. void __fastcall TProgressForm::SetAllowMinimize(bool value)
  559. {
  560. MinimizeItem->Visible = value;
  561. }
  562. //---------------------------------------------------------------------------
  563. void __fastcall TProgressForm::SetReadOnly(bool value)
  564. {
  565. if (FReadOnly != value)
  566. {
  567. FReadOnly = value;
  568. if (!value)
  569. {
  570. ResetOnceDoneOperation();
  571. }
  572. UpdateControls();
  573. }
  574. }
  575. //---------------------------------------------------------------------------
  576. void __fastcall TProgressForm::ResetOnceDoneOperation()
  577. {
  578. SetOnceDoneOperation(odoIdle);
  579. }
  580. //---------------------------------------------------------------------------
  581. void __fastcall TProgressForm::CMDialogKey(TCMDialogKey & Message)
  582. {
  583. if (Message.CharCode == VK_TAB)
  584. {
  585. Toolbar->KeyboardOpen(L'\0', false);
  586. Message.Result = 1;
  587. }
  588. else
  589. {
  590. TForm::Dispatch(&Message);
  591. }
  592. }
  593. //---------------------------------------------------------------------------
  594. void __fastcall TProgressForm::Dispatch(void * AMessage)
  595. {
  596. TMessage & Message = *reinterpret_cast<TMessage *>(AMessage);
  597. if (Message.Msg == WM_CLOSE)
  598. {
  599. CancelOperation();
  600. }
  601. else if (Message.Msg == CM_DIALOGKEY)
  602. {
  603. CMDialogKey(reinterpret_cast<TCMDialogKey &>(Message));
  604. }
  605. else
  606. {
  607. TForm::Dispatch(AMessage);
  608. }
  609. }
  610. //---------------------------------------------------------------------------
  611. void __fastcall TProgressForm::MoveToQueueItemClick(TObject * /*Sender*/)
  612. {
  613. FMoveToQueue = true;
  614. UpdateControls();
  615. }
  616. //---------------------------------------------------------------------------
  617. void __fastcall TProgressForm::OnceDoneItemClick(TObject * Sender)
  618. {
  619. SetOnceDoneItem(dynamic_cast<TTBCustomItem *>(Sender));
  620. }
  621. //---------------------------------------------------------------------------
  622. void __fastcall TProgressForm::CycleOnceDoneItemClick(TObject * /*Sender*/)
  623. {
  624. TTBCustomItem * Item = CurrentOnceDoneItem();
  625. int Index = Item->Parent->IndexOf(Item);
  626. DebugAssert(Index >= 0);
  627. if (Index < Item->Parent->Count - 1)
  628. {
  629. Index++;
  630. }
  631. else
  632. {
  633. Index = 0;
  634. }
  635. SetOnceDoneItem(Item->Parent->Items[Index]);
  636. }
  637. //---------------------------------------------------------------------------
  638. UnicodeString __fastcall TProgressForm::ItemSpeed(const UnicodeString & Text,
  639. TTBXComboBoxItem * Item)
  640. {
  641. // Keep in sync with TNonVisualDataModule::QueueItemSpeed
  642. FCPSLimit = GetSpeedLimit(Text);
  643. UnicodeString Result = SetSpeedLimit(FCPSLimit);
  644. SaveToHistory(Item->Strings, Result);
  645. CustomWinConfiguration->History[L"SpeedLimit"] = Item->Strings;
  646. return Result;
  647. }
  648. //---------------------------------------------------------------------------
  649. void __fastcall TProgressForm::SpeedComboBoxItemAcceptText(TObject * Sender,
  650. UnicodeString & NewText, bool & /*Accept*/)
  651. {
  652. TTBXComboBoxItem * Item = dynamic_cast<TTBXComboBoxItem *>(Sender);
  653. NewText = ItemSpeed(NewText, Item);
  654. }
  655. //---------------------------------------------------------------------------
  656. void __fastcall TProgressForm::SpeedComboBoxItemItemClick(TObject * Sender)
  657. {
  658. TTBXComboBoxItem * Item = dynamic_cast<TTBXComboBoxItem *>(Sender);
  659. Item->Text = ItemSpeed(Item->Text, Item);
  660. }
  661. //---------------------------------------------------------------------------
  662. void __fastcall TProgressForm::SpeedComboBoxItemAdjustImageIndex(
  663. TTBXComboBoxItem * Sender, const UnicodeString /*AText*/, int /*AIndex*/, int & ImageIndex)
  664. {
  665. // Use fixed image (do not change image by item index)
  666. ImageIndex = Sender->ImageIndex;
  667. }
  668. //---------------------------------------------------------------------------
  669. void __fastcall TProgressForm::SpeedComboBoxItemClick(TObject * Sender)
  670. {
  671. ClickToolbarItem(DebugNotNull(dynamic_cast<TTBCustomItem *>(Sender)), false);
  672. }
  673. //---------------------------------------------------------------------------
  674. void __fastcall TProgressForm::ClearCancel()
  675. {
  676. if (DebugAlwaysTrue(FCancel == csCancelFile))
  677. {
  678. FPendingSkip = true;
  679. }
  680. FCancel = csContinue;
  681. UpdateControls();
  682. }
  683. //---------------------------------------------------------------------------
  684. void __fastcall TProgressForm::SetCancelLower(TCancelStatus ACancel)
  685. {
  686. if (FCancel < ACancel)
  687. {
  688. FCancel = ACancel;
  689. UpdateControls();
  690. }
  691. }
  692. //---------------------------------------------------------------------------
  693. void __fastcall TProgressForm::SkipItemClick(TObject * /*Sender*/)
  694. {
  695. SetCancelLower(csCancelFile);
  696. }
  697. //---------------------------------------------------------------------------