QueueController.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include <CoreMain.h>
  6. #include <Queue.h>
  7. #include <TextsWin.h>
  8. #include <GUITools.h>
  9. #include "QueueController.h"
  10. //---------------------------------------------------------------------------
  11. #pragma package(smart_init)
  12. //---------------------------------------------------------------------------
  13. __fastcall TQueueController::TQueueController(TListView * ListView)
  14. {
  15. FListView = ListView;
  16. assert(FListView != NULL);
  17. assert(FListView->OnDblClick == NULL);
  18. FListView->OnDblClick = QueueViewDblClick;
  19. assert(FListView->OnKeyDown == NULL);
  20. FListView->OnKeyDown = QueueViewKeyDown;
  21. FQueueStatus = NULL;
  22. FOnChange = NULL;
  23. }
  24. //---------------------------------------------------------------------------
  25. __fastcall TQueueController::~TQueueController()
  26. {
  27. assert(FListView->OnDblClick == QueueViewDblClick);
  28. FListView->OnDblClick = NULL;
  29. assert(FListView->OnKeyDown == QueueViewKeyDown);
  30. FListView->OnKeyDown = NULL;
  31. }
  32. //---------------------------------------------------------------------------
  33. TQueueItemProxy * __fastcall TQueueController::QueueViewItemToQueueItem(
  34. TListItem * Item, bool * Detail)
  35. {
  36. assert(Item != NULL);
  37. bool ADetail = false;
  38. int Index = Item->Index;
  39. if (Index < FQueueStatus->ActiveCount * 2)
  40. {
  41. ADetail = ((Index % 2) > 0);
  42. Index /= 2;
  43. }
  44. else
  45. {
  46. Index -= FQueueStatus->ActiveCount;
  47. }
  48. if (Detail != NULL)
  49. {
  50. *Detail = ADetail;
  51. }
  52. return FQueueStatus->Items[Index];
  53. }
  54. //---------------------------------------------------------------------------
  55. TQueueOperation __fastcall TQueueController::DefaultOperation()
  56. {
  57. TQueueItemProxy * QueueItem;
  58. if (FListView->ItemFocused != NULL)
  59. {
  60. QueueItem = QueueViewItemToQueueItem(FListView->ItemFocused);
  61. switch (QueueItem->Status)
  62. {
  63. case TQueueItem::qsPending:
  64. return qoItemExecute;
  65. case TQueueItem::qsQuery:
  66. return qoItemQuery;
  67. case TQueueItem::qsError:
  68. return qoItemError;
  69. case TQueueItem::qsPrompt:
  70. return qoItemPrompt;
  71. case TQueueItem::qsProcessing:
  72. return qoItemPause;
  73. case TQueueItem::qsPaused:
  74. return qoItemResume;
  75. }
  76. }
  77. return qoNone;
  78. }
  79. //---------------------------------------------------------------------------
  80. bool __fastcall TQueueController::AllowOperation(
  81. TQueueOperation Operation)
  82. {
  83. TQueueItemProxy * QueueItem = NULL;
  84. if (FListView->ItemFocused != NULL)
  85. {
  86. QueueItem = QueueViewItemToQueueItem(FListView->ItemFocused);
  87. }
  88. switch (Operation)
  89. {
  90. case qoItemUserAction:
  91. return (QueueItem != NULL) && TQueueItem::IsUserActionStatus(QueueItem->Status);
  92. case qoItemQuery:
  93. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsQuery);
  94. case qoItemError:
  95. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsError);
  96. case qoItemPrompt:
  97. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsPrompt);
  98. case qoItemDelete:
  99. return (QueueItem != NULL) && (QueueItem->Status != TQueueItem::qsDone) &&
  100. !TQueueItem::IsUserActionStatus(QueueItem->Status);
  101. case qoItemExecute:
  102. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsPending);
  103. case qoItemUp:
  104. return (QueueItem != NULL) &&
  105. (QueueItem->Status == TQueueItem::qsPending) &&
  106. (FListView->ItemFocused->Index > (FQueueStatus->ActiveCount * 2));
  107. case qoItemDown:
  108. return (QueueItem != NULL) &&
  109. (QueueItem->Status == TQueueItem::qsPending) &&
  110. (FListView->ItemFocused->Index < (FListView->Items->Count - 1));
  111. case qoItemPause:
  112. return (QueueItem != NULL) &&
  113. (QueueItem->Status == TQueueItem::qsProcessing);
  114. case qoItemResume:
  115. return (QueueItem != NULL) &&
  116. (QueueItem->Status == TQueueItem::qsPaused);
  117. case qoPauseAll:
  118. case qoResumeAll:
  119. {
  120. TQueueItem::TStatus Status =
  121. (Operation == qoPauseAll) ? TQueueItem::qsProcessing : TQueueItem::qsPaused;
  122. bool Result = false;
  123. for (int i = 0; !Result && (i < FQueueStatus->ActiveCount); i++)
  124. {
  125. QueueItem = FQueueStatus->Items[i];
  126. Result = (QueueItem->Status == Status);
  127. }
  128. return Result;
  129. }
  130. default:
  131. assert(false);
  132. return false;
  133. }
  134. }
  135. //---------------------------------------------------------------------------
  136. void __fastcall TQueueController::ExecuteOperation(TQueueOperation Operation)
  137. {
  138. TQueueItemProxy * QueueItem = NULL;
  139. if (FListView->ItemFocused != NULL)
  140. {
  141. QueueItem = QueueViewItemToQueueItem(FListView->ItemFocused);
  142. }
  143. if (QueueItem != NULL)
  144. {
  145. switch (Operation)
  146. {
  147. case qoItemUserAction:
  148. case qoItemQuery:
  149. case qoItemError:
  150. case qoItemPrompt:
  151. QueueItem->ProcessUserAction();
  152. break;
  153. case qoItemExecute:
  154. QueueItem->ExecuteNow();
  155. break;
  156. case qoItemUp:
  157. case qoItemDown:
  158. QueueItem->Move(Operation == qoItemUp);
  159. break;
  160. case qoItemDelete:
  161. QueueItem->Delete();
  162. break;
  163. case qoItemPause:
  164. QueueItem->Pause();
  165. break;
  166. case qoItemResume:
  167. QueueItem->Resume();
  168. break;
  169. case qoPauseAll:
  170. case qoResumeAll:
  171. {
  172. for (int i = 0; i < FQueueStatus->ActiveCount; i++)
  173. {
  174. QueueItem = FQueueStatus->Items[i];
  175. if ((Operation == qoPauseAll) && (QueueItem->Status == TQueueItem::qsProcessing))
  176. {
  177. QueueItem->Pause();
  178. }
  179. else if ((Operation == qoResumeAll) && (QueueItem->Status == TQueueItem::qsPaused))
  180. {
  181. QueueItem->Resume();
  182. }
  183. }
  184. }
  185. break;
  186. default:
  187. assert(false);
  188. break;
  189. }
  190. }
  191. }
  192. //---------------------------------------------------------------------------
  193. void __fastcall TQueueController::FillQueueViewItem(TListItem * Item,
  194. TQueueItemProxy * QueueItem, bool Detail)
  195. {
  196. assert(!Detail || (QueueItem->Status != TQueueItem::qsPending));
  197. assert((Item->Data == NULL) || (Item->Data == QueueItem));
  198. Item->Data = QueueItem;
  199. AnsiString ProgressStr;
  200. int State = -1;
  201. switch (QueueItem->Status)
  202. {
  203. case TQueueItem::qsPending:
  204. ProgressStr = LoadStr(QUEUE_PENDING);
  205. break;
  206. case TQueueItem::qsConnecting:
  207. ProgressStr = LoadStr(QUEUE_CONNECTING);
  208. break;
  209. case TQueueItem::qsQuery:
  210. ProgressStr = LoadStr(QUEUE_QUERY);
  211. State = 4;
  212. break;
  213. case TQueueItem::qsError:
  214. ProgressStr = LoadStr(QUEUE_ERROR);
  215. State = 5;
  216. break;
  217. case TQueueItem::qsPrompt:
  218. ProgressStr = LoadStr(QUEUE_PROMPT);
  219. State = 6;
  220. break;
  221. case TQueueItem::qsPaused:
  222. ProgressStr = LoadStr(QUEUE_PAUSED);
  223. State = 7;
  224. break;
  225. }
  226. bool BlinkHide = QueueItemNeedsFrequentRefresh(QueueItem) &&
  227. !QueueItem->ProcessingUserAction &&
  228. ((GetTickCount() % 1000) >= 500);
  229. int Image = -1;
  230. AnsiString Values[5];
  231. TFileOperationProgressType * ProgressData = QueueItem->ProgressData;
  232. TQueueItem::TInfo * Info = QueueItem->Info;
  233. if (!Detail)
  234. {
  235. switch (Info->Operation)
  236. {
  237. case foCopy:
  238. Image = 2;
  239. break;
  240. case foMove:
  241. Image = 3;
  242. break;
  243. }
  244. State = ((Info->Side == osLocal) ? 1 : 0);
  245. // cannot use ProgressData->Temp as it is set only after the transfer actually starts
  246. Values[0] = Info->Source.IsEmpty() ? LoadStr(PROGRESS_TEMP_DIR) : Info->Source;
  247. Values[1] = Info->Destination.IsEmpty() ? LoadStr(PROGRESS_TEMP_DIR) : Info->Destination;
  248. if (ProgressData != NULL)
  249. {
  250. if (ProgressData->Operation == Info->Operation)
  251. {
  252. Values[2] = FormatBytes(ProgressData->TotalTransfered);
  253. Values[3] = FormatDateTimeSpan(Configuration->TimeFormat, ProgressData->TimeElapsed());
  254. if (ProgressStr.IsEmpty())
  255. {
  256. ProgressStr = FORMAT("%d%%", (ProgressData->OverallProgress()));
  257. }
  258. }
  259. else if (ProgressData->Operation == foCalculateSize)
  260. {
  261. ProgressStr = LoadStr(QUEUE_CALCULATING_SIZE);
  262. }
  263. }
  264. Values[4] = ProgressStr;
  265. }
  266. else
  267. {
  268. if (ProgressData != NULL)
  269. {
  270. if ((Info->Side == osRemote) || !ProgressData->Temp)
  271. {
  272. Values[0] = ProgressData->FileName;
  273. }
  274. else
  275. {
  276. Values[0] = ExtractFileName(ProgressData->FileName);
  277. }
  278. if (ProgressData->Operation == Info->Operation)
  279. {
  280. Values[2] = FormatBytes(ProgressData->TransferedSize);
  281. Values[3] = FORMAT("%s/s", (FormatBytes(ProgressData->CPS())));
  282. Values[4] = FORMAT("%d%%", (ProgressData->TransferProgress()));
  283. }
  284. }
  285. else
  286. {
  287. Values[0] = ProgressStr;
  288. }
  289. }
  290. Item->StateIndex = (!BlinkHide ? State : -1);
  291. Item->ImageIndex = (!BlinkHide ? Image : -1);
  292. for (int Index = 0; Index < LENOF(Values); Index++)
  293. {
  294. if (Index < Item->SubItems->Count)
  295. {
  296. Item->SubItems->Strings[Index] = Values[Index];
  297. }
  298. else
  299. {
  300. Item->SubItems->Add(Values[Index]);
  301. }
  302. }
  303. }
  304. //---------------------------------------------------------------------------
  305. void __fastcall TQueueController::UpdateQueueStatus(
  306. TTerminalQueueStatus * QueueStatus)
  307. {
  308. FQueueStatus = QueueStatus;
  309. if (FQueueStatus != NULL)
  310. {
  311. TQueueItemProxy * QueueItem;
  312. TListItem * Item;
  313. int Index = 0;
  314. for (int ItemIndex = 0; ItemIndex < FQueueStatus->Count; ItemIndex++)
  315. {
  316. QueueItem = FQueueStatus->Items[ItemIndex];
  317. int Index2 = Index;
  318. while ((Index2 < FListView->Items->Count) &&
  319. (FListView->Items->Item[Index2]->Data != QueueItem))
  320. {
  321. Index2++;
  322. }
  323. if (Index2 < FListView->Items->Count)
  324. {
  325. while (Index < Index2)
  326. {
  327. FListView->Items->Delete(Index);
  328. Index2--;
  329. }
  330. }
  331. if (Index == FListView->Items->Count)
  332. {
  333. Item = FListView->Items->Add();
  334. }
  335. else if (FListView->Items->Item[Index]->Data != QueueItem)
  336. {
  337. Item = FListView->Items->Insert(Index);
  338. }
  339. else
  340. {
  341. Item = FListView->Items->Item[Index];
  342. assert(Item->Data == QueueItem);
  343. }
  344. FillQueueViewItem(Item, QueueItem, false);
  345. Index++;
  346. assert((QueueItem->Status != TQueueItem::qsPending) ==
  347. (ItemIndex < FQueueStatus->ActiveCount));
  348. if (ItemIndex < FQueueStatus->ActiveCount)
  349. {
  350. if (Index == FListView->Items->Count)
  351. {
  352. Item = FListView->Items->Add();
  353. }
  354. else if (FListView->Items->Item[Index]->Data != QueueItem)
  355. {
  356. Item = FListView->Items->Insert(Index);
  357. }
  358. else
  359. {
  360. Item = FListView->Items->Item[Index];
  361. assert(Item->Data == QueueItem);
  362. }
  363. FillQueueViewItem(Item, QueueItem, true);
  364. Index++;
  365. }
  366. }
  367. while (Index < FListView->Items->Count)
  368. {
  369. FListView->Items->Delete(Index);
  370. }
  371. }
  372. else
  373. {
  374. FListView->Items->Clear();
  375. }
  376. DoChange();
  377. }
  378. //---------------------------------------------------------------------------
  379. void __fastcall TQueueController::RefreshQueueItem(TQueueItemProxy * QueueItem)
  380. {
  381. TListItem * NextListItem = NULL;
  382. TListItem * ListItem;
  383. ListItem = FListView->FindData(0, QueueItem, true, false);
  384. assert(ListItem != NULL);
  385. int ItemIndex = ListItem->Index;
  386. if (ItemIndex + 1 < FListView->Items->Count)
  387. {
  388. NextListItem = FListView->Items->Item[ItemIndex + 1];
  389. if (NextListItem->Data != QueueItem)
  390. {
  391. NextListItem = NULL;
  392. }
  393. }
  394. FillQueueViewItem(ListItem, QueueItem, false);
  395. if (NextListItem == NULL)
  396. {
  397. NextListItem = FListView->Items->Insert(ItemIndex + 1);
  398. }
  399. FillQueueViewItem(NextListItem, QueueItem, true);
  400. DoChange();
  401. }
  402. //---------------------------------------------------------------------------
  403. bool __fastcall TQueueController::QueueItemNeedsFrequentRefresh(
  404. TQueueItemProxy * QueueItem)
  405. {
  406. return
  407. (TQueueItem::IsUserActionStatus(QueueItem->Status) ||
  408. (QueueItem->Status == TQueueItem::qsPaused));
  409. }
  410. //---------------------------------------------------------------------------
  411. void __fastcall TQueueController::DoChange()
  412. {
  413. if (FOnChange != NULL)
  414. {
  415. FOnChange(NULL);
  416. }
  417. }
  418. //---------------------------------------------------------------------------
  419. void __fastcall TQueueController::QueueViewDblClick(TObject * /*Sender*/)
  420. {
  421. TQueueOperation Operation = DefaultOperation();
  422. if (Operation != qoNone)
  423. {
  424. ExecuteOperation(Operation);
  425. }
  426. }
  427. //---------------------------------------------------------------------------
  428. void __fastcall TQueueController::QueueViewKeyDown(TObject * /*Sender*/,
  429. WORD & Key, TShiftState /*Shift*/)
  430. {
  431. if (Key == VK_RETURN)
  432. {
  433. TQueueOperation Operation = DefaultOperation();
  434. if (Operation != qoNone)
  435. {
  436. ExecuteOperation(Operation);
  437. }
  438. Key = 0;
  439. }
  440. else if (Key == VK_DELETE)
  441. {
  442. ExecuteOperation(qoItemDelete);
  443. Key = 0;
  444. }
  445. }
  446. //---------------------------------------------------------------------------
  447. bool __fastcall TQueueController::GetEmpty()
  448. {
  449. return (FQueueStatus == NULL) || (FQueueStatus->Count == 0);
  450. }