QueueController.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  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 <WinConfiguration.h>
  10. #include "QueueController.h"
  11. #include <BaseUtils.hpp>
  12. //---------------------------------------------------------------------------
  13. #pragma package(smart_init)
  14. //---------------------------------------------------------------------------
  15. __fastcall TQueueController::TQueueController(TCustomListView * ListView)
  16. {
  17. FListView = static_cast<TListView *>(ListView);
  18. DebugAssert(FListView != NULL);
  19. DebugAssert(FListView->OnDblClick == NULL);
  20. FListView->OnDblClick = QueueViewDblClick;
  21. DebugAssert(FListView->OnKeyDown == NULL);
  22. FListView->OnKeyDown = QueueViewKeyDown;
  23. DebugAssert(FListView->OnCustomDrawItem == NULL);
  24. FListView->OnCustomDrawItem = QueueViewCustomDrawItem;
  25. FQueueStatus = NULL;
  26. FOnChange = NULL;
  27. RememberConfiguration();
  28. }
  29. //---------------------------------------------------------------------------
  30. __fastcall TQueueController::~TQueueController()
  31. {
  32. DebugAssert(FListView->OnDblClick == QueueViewDblClick);
  33. FListView->OnDblClick = NULL;
  34. DebugAssert(FListView->OnKeyDown == QueueViewKeyDown);
  35. FListView->OnKeyDown = NULL;
  36. DebugAssert(FListView->OnCustomDrawItem == QueueViewCustomDrawItem);
  37. FListView->OnCustomDrawItem = NULL;
  38. }
  39. //---------------------------------------------------------------------------
  40. TQueueItemProxy * __fastcall TQueueController::QueueViewItemToQueueItem(TListItem * Item)
  41. {
  42. // previously this method was based on ActiveCount and DoneCount,
  43. // as if we were inconfident about validity of Item->Data pointers,
  44. // not sure why
  45. return static_cast<TQueueItemProxy *>(Item->Data);
  46. }
  47. //---------------------------------------------------------------------------
  48. TQueueOperation __fastcall TQueueController::DefaultOperation()
  49. {
  50. TQueueItemProxy * QueueItem;
  51. if (FListView->ItemFocused != NULL)
  52. {
  53. QueueItem = QueueViewItemToQueueItem(FListView->ItemFocused);
  54. switch (QueueItem->Status)
  55. {
  56. case TQueueItem::qsPending:
  57. return qoItemExecute;
  58. case TQueueItem::qsQuery:
  59. return qoItemQuery;
  60. case TQueueItem::qsError:
  61. return qoItemError;
  62. case TQueueItem::qsPrompt:
  63. return qoItemPrompt;
  64. case TQueueItem::qsProcessing:
  65. return qoItemPause;
  66. case TQueueItem::qsPaused:
  67. return qoItemResume;
  68. }
  69. }
  70. return qoNone;
  71. }
  72. //---------------------------------------------------------------------------
  73. bool __fastcall TQueueController::AllowOperation(
  74. TQueueOperation Operation, unsigned long * Param)
  75. {
  76. TQueueItemProxy * QueueItem = NULL;
  77. if (FListView->ItemFocused != NULL)
  78. {
  79. QueueItem = QueueViewItemToQueueItem(FListView->ItemFocused);
  80. }
  81. switch (Operation)
  82. {
  83. case qoItemUserAction:
  84. return (QueueItem != NULL) && TQueueItem::IsUserActionStatus(QueueItem->Status);
  85. case qoItemQuery:
  86. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsQuery);
  87. case qoItemError:
  88. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsError);
  89. case qoItemPrompt:
  90. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsPrompt);
  91. case qoItemDelete:
  92. return (QueueItem != NULL);
  93. case qoItemExecute:
  94. return (QueueItem != NULL) && (QueueItem->Status == TQueueItem::qsPending);
  95. case qoItemUp:
  96. return (QueueItem != NULL) &&
  97. (QueueItem->Status == TQueueItem::qsPending) &&
  98. // it's not first pending item,
  99. // this is based on assumption that pending items occupy single line always
  100. (FListView->ItemFocused->Index > 0) &&
  101. (QueueViewItemToQueueItem(FListView->Items->Item[FListView->ItemFocused->Index - 1])->Status == TQueueItem::qsPending);
  102. case qoItemDown:
  103. return (QueueItem != NULL) &&
  104. (QueueItem->Status == TQueueItem::qsPending) &&
  105. (FListView->ItemFocused->Index < (FListView->Items->Count - 1));
  106. case qoItemPause:
  107. return (QueueItem != NULL) &&
  108. (QueueItem->Status == TQueueItem::qsProcessing);
  109. case qoItemResume:
  110. return (QueueItem != NULL) &&
  111. (QueueItem->Status == TQueueItem::qsPaused);
  112. case qoItemSpeed:
  113. {
  114. bool Result =
  115. (QueueItem != NULL) && (QueueItem->Status != TQueueItem::qsDone) &&
  116. TFileOperationProgressType::IsTransferOperation(QueueItem->Info->Operation);
  117. if (Result && (Param != NULL))
  118. {
  119. Result = QueueItem->GetCPSLimit(*Param);
  120. }
  121. return Result;
  122. }
  123. case qoPauseAll:
  124. case qoResumeAll:
  125. {
  126. TQueueItem::TStatus Status =
  127. (Operation == qoPauseAll) ? TQueueItem::qsProcessing : TQueueItem::qsPaused;
  128. bool Result = false;
  129. // can be NULL when action update is triggered while disconnecting
  130. if (FQueueStatus != NULL)
  131. {
  132. for (int i = FQueueStatus->DoneCount; !Result && (i < FQueueStatus->DoneAndActiveCount); i++)
  133. {
  134. QueueItem = FQueueStatus->Items[i];
  135. Result = (QueueItem->Status == Status);
  136. }
  137. }
  138. return Result;
  139. }
  140. case qoDeleteAllDone:
  141. return (FQueueStatus != NULL) && (FQueueStatus->DoneCount > 0);
  142. case qoDeleteAll:
  143. return (FQueueStatus != NULL) && (FQueueStatus->Count > 0);
  144. default:
  145. DebugFail();
  146. return false;
  147. }
  148. }
  149. //---------------------------------------------------------------------------
  150. void __fastcall TQueueController::ExecuteOperation(TQueueOperation Operation,
  151. unsigned long Param)
  152. {
  153. TQueueItemProxy * QueueItem = NULL;
  154. if (FListView->ItemFocused != NULL)
  155. {
  156. QueueItem = QueueViewItemToQueueItem(FListView->ItemFocused);
  157. }
  158. switch (Operation)
  159. {
  160. case qoItemUserAction:
  161. case qoItemQuery:
  162. case qoItemError:
  163. case qoItemPrompt:
  164. if (QueueItem != NULL)
  165. {
  166. QueueItem->ProcessUserAction();
  167. }
  168. break;
  169. case qoItemExecute:
  170. if (QueueItem != NULL)
  171. {
  172. QueueItem->ExecuteNow();
  173. }
  174. break;
  175. case qoItemUp:
  176. case qoItemDown:
  177. if (QueueItem != NULL)
  178. {
  179. QueueItem->Move(Operation == qoItemUp);
  180. }
  181. break;
  182. case qoItemDelete:
  183. if (QueueItem != NULL)
  184. {
  185. QueueItem->Delete();
  186. }
  187. break;
  188. case qoItemPause:
  189. if (QueueItem != NULL)
  190. {
  191. QueueItem->Pause();
  192. }
  193. break;
  194. case qoItemResume:
  195. if (QueueItem != NULL)
  196. {
  197. QueueItem->Resume();
  198. }
  199. break;
  200. case qoItemSpeed:
  201. if (QueueItem != NULL)
  202. {
  203. QueueItem->SetCPSLimit(Param);
  204. }
  205. break;
  206. case qoPauseAll:
  207. case qoResumeAll:
  208. {
  209. for (int i = FQueueStatus->DoneCount; i < FQueueStatus->DoneAndActiveCount; i++)
  210. {
  211. QueueItem = FQueueStatus->Items[i];
  212. if ((Operation == qoPauseAll) && (QueueItem->Status == TQueueItem::qsProcessing))
  213. {
  214. QueueItem->Pause();
  215. }
  216. else if ((Operation == qoResumeAll) && (QueueItem->Status == TQueueItem::qsPaused))
  217. {
  218. QueueItem->Resume();
  219. }
  220. }
  221. }
  222. break;
  223. case qoDeleteAllDone:
  224. case qoDeleteAll:
  225. {
  226. int Count = (Operation == qoDeleteAll) ? FQueueStatus->Count : FQueueStatus->DoneCount;
  227. for (int i = 0; i < Count; i++)
  228. {
  229. QueueItem = FQueueStatus->Items[i];
  230. QueueItem->Delete();
  231. }
  232. }
  233. break;
  234. default:
  235. DebugFail();
  236. break;
  237. }
  238. }
  239. //---------------------------------------------------------------------------
  240. static UnicodeString GetTime(TFileOperationProgressType * ProgressData)
  241. {
  242. UnicodeString Result;
  243. if (ProgressData->TotalSizeSet)
  244. {
  245. Result = FormatDateTimeSpan(ProgressData->TotalTimeLeft());
  246. }
  247. else
  248. {
  249. Result = FormatDateTimeSpan(ProgressData->TimeElapsed());
  250. }
  251. return Result;
  252. }
  253. //---------------------------------------------------------------------------
  254. static UnicodeString GetOverallProgress(TFileOperationProgressType * ProgressData)
  255. {
  256. return FORMAT(L"%d%%", (ProgressData->OverallProgress()));
  257. }
  258. //---------------------------------------------------------------------------
  259. void __fastcall TQueueController::FillQueueViewItem(TListItem * Item,
  260. TQueueItemProxy * QueueItem, bool Detail, bool OnlyLine)
  261. {
  262. DebugAssert(!Detail || (QueueItem->Status != TQueueItem::qsPending));
  263. DebugAssert((Item->Data == NULL) || (Item->Data == QueueItem));
  264. Item->Data = QueueItem;
  265. UnicodeString ProgressStr;
  266. int Image = -1;
  267. switch (QueueItem->Status)
  268. {
  269. case TQueueItem::qsDone:
  270. ProgressStr = LoadStr(QUEUE_DONE);
  271. break;
  272. case TQueueItem::qsPending:
  273. ProgressStr = LoadStr(QUEUE_PENDING);
  274. break;
  275. case TQueueItem::qsConnecting:
  276. ProgressStr = LoadStr(QUEUE_CONNECTING);
  277. break;
  278. case TQueueItem::qsQuery:
  279. ProgressStr = LoadStr(QUEUE_QUERY);
  280. Image = 4;
  281. break;
  282. case TQueueItem::qsError:
  283. ProgressStr = LoadStr(QUEUE_ERROR);
  284. Image = 5;
  285. break;
  286. case TQueueItem::qsPrompt:
  287. ProgressStr = LoadStr(QUEUE_PROMPT);
  288. Image = 6;
  289. break;
  290. case TQueueItem::qsPaused:
  291. ProgressStr = LoadStr(QUEUE_PAUSED);
  292. Image = 7;
  293. break;
  294. }
  295. bool BlinkHide = QueueItemNeedsFrequentRefresh(QueueItem) &&
  296. !QueueItem->ProcessingUserAction &&
  297. ((GetTickCount() % MSecsPerSec) >= (MSecsPerSec/2));
  298. int State = -1;
  299. UnicodeString Values[6];
  300. TFileOperationProgressType * ProgressData = QueueItem->ProgressData;
  301. TQueueItem::TInfo * Info = QueueItem->Info;
  302. if (SimpleOperation(QueueItem))
  303. {
  304. DebugAssert(!Detail && Info->Primary);
  305. State = 8;
  306. if ((ProgressData != NULL) && (QueueItem->Status != TQueueItem::qsDone))
  307. {
  308. Values[0] = ProgressData->FileName;
  309. Values[3] = GetTime(ProgressData);
  310. if (ProgressStr.IsEmpty())
  311. {
  312. if (ProgressData->Count > 1)
  313. {
  314. ProgressStr = GetOverallProgress(ProgressData);
  315. }
  316. else
  317. {
  318. ProgressStr = LoadStr(QUEUE_DELETING);
  319. }
  320. }
  321. }
  322. else
  323. {
  324. Values[0] = Info->Source;
  325. }
  326. Values[5] = ProgressStr;
  327. }
  328. else if (!Detail && Info->Primary)
  329. {
  330. switch (Info->Operation)
  331. {
  332. case foCopy:
  333. State = ((Info->Side == osLocal) ? 2 : 0);
  334. break;
  335. case foMove:
  336. State = ((Info->Side == osLocal) ? 3 : 1);
  337. break;
  338. default:
  339. DebugFail();
  340. }
  341. if (!OnlyLine)
  342. {
  343. Image = -1;
  344. ProgressStr = L"";
  345. }
  346. // If both are empty, it's bootstrap item => do not show anything
  347. if (!Info->Source.IsEmpty() || !Info->Destination.IsEmpty())
  348. {
  349. // cannot use ProgressData->Temp as it is set only after the transfer actually starts
  350. Values[0] = Info->Source.IsEmpty() ? LoadStr(PROGRESS_TEMP_DIR) : Info->Source;
  351. Values[1] = Info->Destination.IsEmpty() ? LoadStr(PROGRESS_TEMP_DIR) : Info->Destination;
  352. }
  353. __int64 TotalTransferred = QueueItem->TotalTransferred;
  354. if (TotalTransferred >= 0)
  355. {
  356. Values[2] =
  357. FormatPanelBytes(TotalTransferred, WinConfiguration->FormatSizeBytes);
  358. }
  359. if (ProgressData != NULL)
  360. {
  361. if (ProgressData->Operation == Info->Operation)
  362. {
  363. if (QueueItem->Status != TQueueItem::qsDone)
  364. {
  365. Values[3] = GetTime(ProgressData);
  366. Values[4] = FORMAT(L"%s/s", (FormatBytes(ProgressData->CPS())));
  367. }
  368. if (ProgressStr.IsEmpty())
  369. {
  370. ProgressStr = GetOverallProgress(ProgressData);
  371. }
  372. }
  373. else if (ProgressData->Operation == foCalculateSize)
  374. {
  375. ProgressStr = LoadStr(QUEUE_LISTING);
  376. }
  377. }
  378. Values[5] = ProgressStr;
  379. }
  380. else
  381. {
  382. if (ProgressData != NULL)
  383. {
  384. if ((Info->Side == osRemote) || !ProgressData->Temp)
  385. {
  386. Values[0] = ProgressData->FileName;
  387. }
  388. else
  389. {
  390. Values[0] = ExtractFileName(ProgressData->FileName);
  391. }
  392. if (ProgressData->Operation == Info->Operation)
  393. {
  394. Values[2] =
  395. FormatPanelBytes(ProgressData->TransferredSize, WinConfiguration->FormatSizeBytes);
  396. if (ProgressStr.IsEmpty())
  397. {
  398. ProgressStr = FORMAT(L"%d%%", (ProgressData->TransferProgress()));
  399. }
  400. }
  401. }
  402. Values[5] = ProgressStr;
  403. }
  404. Item->StateIndex = (!BlinkHide ? State : -1);
  405. Item->ImageIndex = (!BlinkHide ? Image : -1);
  406. for (size_t Index = 0; Index < LENOF(Values); Index++)
  407. {
  408. if (Index < static_cast<size_t>(Item->SubItems->Count))
  409. {
  410. Item->SubItems->Strings[Index] = Values[Index];
  411. }
  412. else
  413. {
  414. Item->SubItems->Add(Values[Index]);
  415. }
  416. }
  417. }
  418. //---------------------------------------------------------------------------
  419. TListItem * __fastcall TQueueController::InsertItemFor(TQueueItemProxy * QueueItem, int Index)
  420. {
  421. TListItem * Item;
  422. if (Index == FListView->Items->Count)
  423. {
  424. Item = FListView->Items->Add();
  425. }
  426. else if (FListView->Items->Item[Index]->Data != QueueItem)
  427. {
  428. Item = FListView->Items->Insert(Index);
  429. }
  430. else
  431. {
  432. Item = FListView->Items->Item[Index];
  433. DebugAssert(Item->Data == QueueItem);
  434. }
  435. return Item;
  436. }
  437. //---------------------------------------------------------------------------
  438. void __fastcall TQueueController::UpdateQueueStatus(
  439. TTerminalQueueStatus * QueueStatus)
  440. {
  441. FQueueStatus = QueueStatus;
  442. if (FQueueStatus != NULL)
  443. {
  444. TQueueItemProxy * QueueItem;
  445. TListItem * Item;
  446. int Index = 0;
  447. for (int ItemIndex = 0; ItemIndex < FQueueStatus->Count; ItemIndex++)
  448. {
  449. QueueItem = FQueueStatus->Items[ItemIndex];
  450. int Index2 = Index;
  451. while ((Index2 < FListView->Items->Count) &&
  452. (FListView->Items->Item[Index2]->Data != QueueItem))
  453. {
  454. Index2++;
  455. }
  456. if (Index2 < FListView->Items->Count)
  457. {
  458. while (Index < Index2)
  459. {
  460. FListView->Items->Delete(Index);
  461. Index2--;
  462. }
  463. }
  464. Item = InsertItemFor(QueueItem, Index);
  465. bool HasDetailsLine = UseDetailsLine(ItemIndex, QueueItem);
  466. FillQueueViewItem(Item, QueueItem, false, !HasDetailsLine);
  467. Index++;
  468. DebugAssert((QueueItem->Status != TQueueItem::qsPending) ==
  469. (ItemIndex < FQueueStatus->DoneAndActiveCount));
  470. if (HasDetailsLine)
  471. {
  472. Item = InsertItemFor(QueueItem, Index);
  473. FillQueueViewItem(Item, QueueItem, true, false);
  474. Index++;
  475. }
  476. }
  477. while (Index < FListView->Items->Count)
  478. {
  479. FListView->Items->Delete(Index);
  480. }
  481. }
  482. else
  483. {
  484. FListView->Items->Clear();
  485. }
  486. DoChange();
  487. }
  488. //---------------------------------------------------------------------------
  489. bool TQueueController::SimpleOperation(TQueueItemProxy * QueueItem)
  490. {
  491. return (QueueItem->Info->Operation == foDelete); // basically any non-transfer, but we support delete now only
  492. }
  493. //---------------------------------------------------------------------------
  494. bool __fastcall TQueueController::UseDetailsLine(int ItemIndex, TQueueItemProxy * QueueItem)
  495. {
  496. return
  497. (ItemIndex >= FQueueStatus->DoneCount) &&
  498. (ItemIndex < FQueueStatus->DoneAndActiveCount) &&
  499. QueueItem->Info->Primary &&
  500. !QueueItem->Info->SingleFile &&
  501. !SimpleOperation(QueueItem) &&
  502. ((QueueItem->ProgressData == NULL) || !QueueItem->ProgressData->Done);
  503. }
  504. //---------------------------------------------------------------------------
  505. void __fastcall TQueueController::RefreshQueueItem(TQueueItemProxy * QueueItem)
  506. {
  507. TListItem * NextListItem = NULL;
  508. TListItem * ListItem;
  509. ListItem = FListView->FindData(0, QueueItem, true, false);
  510. DebugAssert(ListItem != NULL);
  511. int Index = ListItem->Index;
  512. if (Index + 1 < FListView->Items->Count)
  513. {
  514. NextListItem = FListView->Items->Item[Index + 1];
  515. if (NextListItem->Data != QueueItem)
  516. {
  517. NextListItem = NULL;
  518. }
  519. }
  520. bool HasDetailsLine = UseDetailsLine(QueueItem->Index, QueueItem);
  521. FillQueueViewItem(ListItem, QueueItem, false, !HasDetailsLine);
  522. if (HasDetailsLine)
  523. {
  524. if (NextListItem == NULL)
  525. {
  526. NextListItem = FListView->Items->Insert(Index + 1);
  527. }
  528. FillQueueViewItem(NextListItem, QueueItem, true, false);
  529. }
  530. else
  531. {
  532. if (NextListItem != NULL)
  533. {
  534. NextListItem->Delete();
  535. }
  536. }
  537. DoChange();
  538. }
  539. //---------------------------------------------------------------------------
  540. bool __fastcall TQueueController::QueueItemNeedsFrequentRefresh(
  541. TQueueItemProxy * QueueItem)
  542. {
  543. return
  544. (TQueueItem::IsUserActionStatus(QueueItem->Status) ||
  545. (QueueItem->Status == TQueueItem::qsPaused));
  546. }
  547. //---------------------------------------------------------------------------
  548. void __fastcall TQueueController::DoChange()
  549. {
  550. if (FOnChange != NULL)
  551. {
  552. FOnChange(NULL);
  553. }
  554. }
  555. //---------------------------------------------------------------------------
  556. void __fastcall TQueueController::QueueViewDblClick(TObject * /*Sender*/)
  557. {
  558. TQueueOperation Operation = DefaultOperation();
  559. if (Operation != qoNone)
  560. {
  561. ExecuteOperation(Operation);
  562. }
  563. }
  564. //---------------------------------------------------------------------------
  565. void __fastcall TQueueController::QueueViewKeyDown(TObject * /*Sender*/,
  566. WORD & Key, TShiftState /*Shift*/)
  567. {
  568. if (Key == VK_RETURN)
  569. {
  570. TQueueOperation Operation = DefaultOperation();
  571. if (Operation != qoNone)
  572. {
  573. ExecuteOperation(Operation);
  574. }
  575. Key = 0;
  576. }
  577. else if (Key == VK_DELETE)
  578. {
  579. ExecuteOperation(qoItemDelete);
  580. Key = 0;
  581. }
  582. }
  583. //---------------------------------------------------------------------------
  584. void __fastcall TQueueController::QueueViewCustomDrawItem(TCustomListView * Sender,
  585. TListItem * Item, TCustomDrawState /*State*/, bool & /*DefaultDraw*/)
  586. {
  587. TQueueItemProxy * QueueItem = QueueViewItemToQueueItem(Item);
  588. if (QueueItem->Status == TQueueItem::qsDone)
  589. {
  590. Sender->Canvas->Font->Color = clGrayText;
  591. }
  592. }
  593. //---------------------------------------------------------------------------
  594. bool __fastcall TQueueController::GetEmpty()
  595. {
  596. return (FQueueStatus == NULL) || (FQueueStatus->Count == 0);
  597. }
  598. //---------------------------------------------------------------------------
  599. void __fastcall TQueueController::RememberConfiguration()
  600. {
  601. FFormatSizeBytes = WinConfiguration->FormatSizeBytes;
  602. }
  603. //---------------------------------------------------------------------------
  604. bool __fastcall TQueueController::NeedRefresh()
  605. {
  606. bool Result = (WinConfiguration->FormatSizeBytes != FFormatSizeBytes);
  607. RememberConfiguration();
  608. return Result;
  609. }
  610. //---------------------------------------------------------------------------
  611. TQueueItemProxy * __fastcall TQueueController::GetFocusedPrimaryItem()
  612. {
  613. TQueueItemProxy * Result = NULL;
  614. TListItem * PrimaryItemOfFocused = FListView->ItemFocused;
  615. if (PrimaryItemOfFocused != NULL)
  616. {
  617. while (!QueueViewItemToQueueItem(PrimaryItemOfFocused)->Info->Primary &&
  618. DebugAlwaysTrue(PrimaryItemOfFocused->Index > 0))
  619. {
  620. PrimaryItemOfFocused = FListView->Items->Item[PrimaryItemOfFocused->Index - 1];
  621. }
  622. Result = QueueViewItemToQueueItem(PrimaryItemOfFocused);
  623. }
  624. return Result;
  625. }