QueueController.cpp 14 KB

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