Bookmarks.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. //---------------------------------------------------------------------------
  2. #include <CorePCH.h>
  3. #pragma hdrstop
  4. #include "NamedObjs.h"
  5. #include "Bookmarks.h"
  6. #include "Configuration.h"
  7. #include "HierarchicalStorage.h"
  8. //---------------------------------------------------------------------------
  9. __fastcall TBookmarks::TBookmarks(): TObject()
  10. {
  11. FSharedKey = TNamedObjectList::HiddenPrefix + L"shared";
  12. FBookmarkLists = CreateSortedStringList(false, Types::dupError);
  13. }
  14. //---------------------------------------------------------------------------
  15. __fastcall TBookmarks::~TBookmarks()
  16. {
  17. Clear();
  18. SAFE_DESTROY(FBookmarkLists);
  19. }
  20. //---------------------------------------------------------------------------
  21. void __fastcall TBookmarks::Clear()
  22. {
  23. for (int i = 0; i < FBookmarkLists->Count; i++)
  24. {
  25. delete FBookmarkLists->Objects[i];
  26. }
  27. FBookmarkLists->Clear();
  28. }
  29. //---------------------------------------------------------------------------
  30. UnicodeString TBookmarks::Keys[] = { L"Local", L"Remote", L"ShortCuts", L"Options" };
  31. //---------------------------------------------------------------------------
  32. void __fastcall TBookmarks::Load(THierarchicalStorage * Storage)
  33. {
  34. for (int i = 0; i <= 3; i++)
  35. {
  36. if (Storage->OpenSubKey(Keys[i], false))
  37. {
  38. TStrings * BookmarkKeys = new TStringList();
  39. try
  40. {
  41. Storage->GetSubKeyNames(BookmarkKeys);
  42. for (int Index = 0; Index < BookmarkKeys->Count; Index++)
  43. {
  44. UnicodeString Key = BookmarkKeys->Strings[Index];
  45. if (Storage->OpenSubKey(Key, false))
  46. {
  47. TBookmarkList * BookmarkList = Bookmarks[Key];
  48. if (!BookmarkList)
  49. {
  50. BookmarkList = new TBookmarkList();
  51. FBookmarkLists->AddObject(Key, BookmarkList);
  52. }
  53. if (i < 3)
  54. {
  55. LoadLevel(Storage, L"", i, BookmarkList);
  56. }
  57. else
  58. {
  59. BookmarkList->LoadOptions(Storage);
  60. }
  61. Storage->CloseSubKey();
  62. }
  63. }
  64. }
  65. __finally
  66. {
  67. delete BookmarkKeys;
  68. }
  69. Storage->CloseSubKey();
  70. }
  71. }
  72. ModifyAll(false);
  73. }
  74. //---------------------------------------------------------------------------
  75. void __fastcall TBookmarks::LoadLevel(THierarchicalStorage * Storage, const UnicodeString Key,
  76. int Index, TBookmarkList * BookmarkList)
  77. {
  78. TStrings * Names = new TStringList();
  79. try
  80. {
  81. Storage->GetValueNames(Names);
  82. UnicodeString Name;
  83. UnicodeString Directory;
  84. TShortCut ShortCut = TShortCut();
  85. for (int i = 0; i < Names->Count; i++)
  86. {
  87. Name = Names->Strings[i];
  88. bool IsDirectory = (Index == 0) || (Index == 1);
  89. if (IsDirectory)
  90. {
  91. Directory = Storage->ReadString(Name, L"");
  92. }
  93. else
  94. {
  95. Directory = L""; // use only in case of malformed config
  96. ShortCut = (TShortCut)Storage->ReadInteger(Name, 0);
  97. }
  98. TBookmark * Bookmark;
  99. if (IsNumber(Name))
  100. {
  101. DebugAssert(IsDirectory); // unless malformed
  102. Name = Directory;
  103. }
  104. if (!Name.IsEmpty())
  105. {
  106. Bookmark = BookmarkList->FindByName(Key, Name);
  107. bool New;
  108. New = (Bookmark == NULL);
  109. if (New)
  110. {
  111. Bookmark = new TBookmark();
  112. Bookmark->Node = Key;
  113. Bookmark->Name = Name;
  114. }
  115. switch (Index)
  116. {
  117. case 0:
  118. Bookmark->Local = Directory;
  119. break;
  120. case 1:
  121. Bookmark->Remote = Directory;
  122. break;
  123. case 2:
  124. Bookmark->ShortCut = ShortCut;
  125. break;
  126. }
  127. if (New)
  128. {
  129. BookmarkList->Add(Bookmark);
  130. }
  131. }
  132. }
  133. Storage->GetSubKeyNames(Names);
  134. for (int i = 0; i < Names->Count; i++)
  135. {
  136. Name = Names->Strings[i];
  137. if (Storage->OpenSubKey(Name, false))
  138. {
  139. LoadLevel(Storage, Key + (Key.IsEmpty() ? L"" : L"/") + Name, Index, BookmarkList);
  140. Storage->CloseSubKey();
  141. }
  142. }
  143. }
  144. __finally
  145. {
  146. delete Names;
  147. }
  148. }
  149. //---------------------------------------------------------------------------
  150. void __fastcall TBookmarks::Save(THierarchicalStorage * Storage, bool All)
  151. {
  152. for (int i = 0; i <= 3; i++)
  153. {
  154. if (Storage->OpenSubKey(Keys[i], true))
  155. {
  156. for (int Index = 0; Index < FBookmarkLists->Count; Index++)
  157. {
  158. TBookmarkList * BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[Index]);
  159. if (All || BookmarkList->Modified)
  160. {
  161. UnicodeString Key = FBookmarkLists->Strings[Index];
  162. Storage->RecursiveDeleteSubKey(Key);
  163. if (Storage->OpenSubKey(Key, true))
  164. {
  165. if (i < 3)
  166. {
  167. for (int IndexB = 0; IndexB < BookmarkList->Count; IndexB++)
  168. {
  169. TBookmark * Bookmark = BookmarkList->Bookmarks[IndexB];
  170. // avoid creating empty subfolder if there's no shortcut
  171. if ((i == 0) || (i == 1) ||
  172. ((i == 2) && (Bookmark->ShortCut != 0)))
  173. {
  174. bool HasNode = !Bookmark->Node.IsEmpty();
  175. if (!HasNode || Storage->OpenSubKey(Bookmark->Node, true))
  176. {
  177. switch (i)
  178. {
  179. case 0:
  180. Storage->WriteString(Bookmark->Name, Bookmark->Local);
  181. break;
  182. case 1:
  183. Storage->WriteString(Bookmark->Name, Bookmark->Remote);
  184. break;
  185. case 2:
  186. DebugAssert(Bookmark->ShortCut != 0);
  187. Storage->WriteInteger(Bookmark->Name, Bookmark->ShortCut);
  188. break;
  189. }
  190. if (HasNode)
  191. {
  192. Storage->CloseSubKey();
  193. }
  194. }
  195. }
  196. }
  197. }
  198. else
  199. {
  200. BookmarkList->SaveOptions(Storage);
  201. }
  202. Storage->CloseSubKey();
  203. }
  204. }
  205. }
  206. Storage->CloseSubKey();
  207. }
  208. }
  209. if (!All)
  210. {
  211. ModifyAll(false);
  212. }
  213. }
  214. //---------------------------------------------------------------------------
  215. void __fastcall TBookmarks::ModifyAll(bool Modify)
  216. {
  217. TBookmarkList * BookmarkList;
  218. for (int i = 0; i < FBookmarkLists->Count; i++)
  219. {
  220. BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[i]);
  221. DebugAssert(BookmarkList);
  222. BookmarkList->Modified = Modify;
  223. }
  224. }
  225. //---------------------------------------------------------------------------
  226. TBookmarkList * __fastcall TBookmarks::GetBookmarks(UnicodeString Index)
  227. {
  228. int I = FBookmarkLists->IndexOf(Index);
  229. if (I >= 0)
  230. {
  231. return dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[I]);
  232. }
  233. else
  234. {
  235. return NULL;
  236. }
  237. }
  238. //---------------------------------------------------------------------------
  239. void __fastcall TBookmarks::SetBookmarks(UnicodeString Index, TBookmarkList * value)
  240. {
  241. int I = FBookmarkLists->IndexOf(Index);
  242. if (I >= 0)
  243. {
  244. TBookmarkList * BookmarkList;
  245. BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[I]);
  246. BookmarkList->Assign(value);
  247. }
  248. else
  249. {
  250. TBookmarkList * BookmarkList = new TBookmarkList();
  251. BookmarkList->Assign(value);
  252. FBookmarkLists->AddObject(Index, BookmarkList);
  253. }
  254. }
  255. //---------------------------------------------------------------------------
  256. TBookmarkList * __fastcall TBookmarks::GetSharedBookmarks()
  257. {
  258. return GetBookmarks(FSharedKey);
  259. }
  260. //---------------------------------------------------------------------------
  261. void __fastcall TBookmarks::SetSharedBookmarks(TBookmarkList * value)
  262. {
  263. SetBookmarks(FSharedKey, value);
  264. }
  265. //---------------------------------------------------------------------------
  266. //---------------------------------------------------------------------------
  267. __fastcall TBookmarkList::TBookmarkList(): TPersistent()
  268. {
  269. FModified = false;
  270. FBookmarks = new TStringList();
  271. FBookmarks->CaseSensitive = false;
  272. FOpenedNodes = CreateSortedStringList();
  273. }
  274. //---------------------------------------------------------------------------
  275. __fastcall TBookmarkList::~TBookmarkList()
  276. {
  277. Clear();
  278. SAFE_DESTROY(FBookmarks);
  279. SAFE_DESTROY(FOpenedNodes);
  280. }
  281. //---------------------------------------------------------------------------
  282. void __fastcall TBookmarkList::Clear()
  283. {
  284. for (int i = 0; i < FBookmarks->Count; i++)
  285. {
  286. delete FBookmarks->Objects[i];
  287. }
  288. FBookmarks->Clear();
  289. FOpenedNodes->Clear();
  290. }
  291. //---------------------------------------------------------------------------
  292. void __fastcall TBookmarkList::Assign(TPersistent * Source)
  293. {
  294. TBookmarkList * SourceList;
  295. SourceList = dynamic_cast<TBookmarkList *>(Source);
  296. if (SourceList)
  297. {
  298. Clear();
  299. for (int i = 0; i < SourceList->FBookmarks->Count; i++)
  300. {
  301. TBookmark * Bookmark = new TBookmark();
  302. Bookmark->Assign(dynamic_cast<TBookmark *>(SourceList->FBookmarks->Objects[i]));
  303. Add(Bookmark);
  304. }
  305. FOpenedNodes->Assign(SourceList->FOpenedNodes);
  306. Modified = SourceList->Modified;
  307. }
  308. else
  309. {
  310. TPersistent::Assign(Source);
  311. }
  312. }
  313. //---------------------------------------------------------------------------
  314. void __fastcall TBookmarkList::LoadOptions(THierarchicalStorage * Storage)
  315. {
  316. FOpenedNodes->CommaText = Storage->ReadString(L"OpenedNodes", L"");
  317. }
  318. //---------------------------------------------------------------------------
  319. void __fastcall TBookmarkList::SaveOptions(THierarchicalStorage * Storage)
  320. {
  321. Storage->WriteString(L"OpenedNodes", FOpenedNodes->CommaText);
  322. }
  323. //---------------------------------------------------------------------------
  324. void __fastcall TBookmarkList::Add(TBookmark * Bookmark)
  325. {
  326. Insert(Count, Bookmark);
  327. }
  328. //---------------------------------------------------------------------------
  329. void __fastcall TBookmarkList::InsertBefore(TBookmark * BeforeBookmark, TBookmark * Bookmark)
  330. {
  331. DebugAssert(BeforeBookmark);
  332. int I = FBookmarks->IndexOf(BeforeBookmark->Key);
  333. DebugAssert(I >= 0);
  334. Insert(I, Bookmark);
  335. }
  336. //---------------------------------------------------------------------------
  337. void __fastcall TBookmarkList::MoveTo(TBookmark * ToBookmark,
  338. TBookmark * Bookmark, bool Before)
  339. {
  340. DebugAssert(ToBookmark != NULL);
  341. int NewIndex = FBookmarks->IndexOf(ToBookmark->Key);
  342. DebugAssert(Bookmark != NULL);
  343. int OldIndex = FBookmarks->IndexOf(Bookmark->Key);
  344. if (Before && (NewIndex > OldIndex))
  345. {
  346. // otherwise item is moved after the item in the target index
  347. NewIndex--;
  348. }
  349. else if (!Before && (NewIndex < OldIndex))
  350. {
  351. NewIndex++;
  352. }
  353. FModified = true;
  354. FBookmarks->Move(OldIndex, NewIndex);
  355. }
  356. //---------------------------------------------------------------------------
  357. void __fastcall TBookmarkList::Insert(int Index, TBookmark * Bookmark)
  358. {
  359. DebugAssert(Bookmark);
  360. DebugAssert(!Bookmark->FOwner);
  361. DebugAssert(!Bookmark->Name.IsEmpty());
  362. FModified = true;
  363. Bookmark->FOwner = this;
  364. if (FBookmarks->IndexOf(Bookmark->Key) >= 0)
  365. {
  366. throw Exception(FMTLOAD(DUPLICATE_BOOKMARK, (Bookmark->Name)));
  367. }
  368. FBookmarks->InsertObject(Index, Bookmark->Key, Bookmark);
  369. }
  370. //---------------------------------------------------------------------------
  371. void __fastcall TBookmarkList::Delete(TBookmark * Bookmark)
  372. {
  373. DebugAssert(Bookmark);
  374. DebugAssert(Bookmark->FOwner == this);
  375. int I = IndexOf(Bookmark);
  376. DebugAssert(I >= 0);
  377. FModified = true;
  378. Bookmark->FOwner = NULL;
  379. FBookmarks->Delete(I);
  380. delete Bookmark;
  381. }
  382. //---------------------------------------------------------------------------
  383. int __fastcall TBookmarkList::IndexOf(TBookmark * Bookmark)
  384. {
  385. return FBookmarks->IndexOf(Bookmark->Key);
  386. }
  387. //---------------------------------------------------------------------------
  388. void __fastcall TBookmarkList::KeyChanged(int Index)
  389. {
  390. DebugAssert(Index < Count);
  391. TBookmark * Bookmark = dynamic_cast<TBookmark *>(FBookmarks->Objects[Index]);
  392. DebugAssert(FBookmarks->Strings[Index] != Bookmark->Key);
  393. if (FBookmarks->IndexOf(Bookmark->Key) >= 0)
  394. {
  395. throw Exception(FMTLOAD(DUPLICATE_BOOKMARK, (Bookmark->Name)));
  396. }
  397. FBookmarks->Strings[Index] = Bookmark->Key;
  398. }
  399. //---------------------------------------------------------------------------
  400. TBookmark * __fastcall TBookmarkList::FindByName(const UnicodeString Node, const UnicodeString Name)
  401. {
  402. int I = FBookmarks->IndexOf(TBookmark::BookmarkKey(Node, Name));
  403. TBookmark * Bookmark = I >= 0 ? dynamic_cast<TBookmark *>(FBookmarks->Objects[I]) : NULL;
  404. DebugAssert(!Bookmark || (Bookmark->Node == Node && Bookmark->Name == Name));
  405. return Bookmark;
  406. }
  407. //---------------------------------------------------------------------------
  408. TBookmark * __fastcall TBookmarkList::FindByShortCut(TShortCut ShortCut)
  409. {
  410. for (int Index = 0; Index < FBookmarks->Count; Index++)
  411. {
  412. if (Bookmarks[Index]->ShortCut == ShortCut)
  413. {
  414. return Bookmarks[Index];
  415. }
  416. }
  417. return NULL;
  418. }
  419. //---------------------------------------------------------------------------
  420. int __fastcall TBookmarkList::GetCount()
  421. {
  422. return FBookmarks->Count;
  423. }
  424. //---------------------------------------------------------------------------
  425. TBookmark * __fastcall TBookmarkList::GetBookmarks(int Index)
  426. {
  427. TBookmark * Bookmark = dynamic_cast<TBookmark *>(FBookmarks->Objects[Index]);
  428. DebugAssert(Bookmark);
  429. return Bookmark;
  430. }
  431. //---------------------------------------------------------------------------
  432. bool __fastcall TBookmarkList::GetNodeOpened(UnicodeString Index)
  433. {
  434. return (FOpenedNodes->IndexOf(Index) >= 0);
  435. }
  436. //---------------------------------------------------------------------------
  437. void __fastcall TBookmarkList::SetNodeOpened(UnicodeString Index, bool value)
  438. {
  439. int I = FOpenedNodes->IndexOf(Index);
  440. if ((I >= 0) != value)
  441. {
  442. if (value)
  443. {
  444. FOpenedNodes->Add(Index);
  445. }
  446. else
  447. {
  448. FOpenedNodes->Delete(I);
  449. }
  450. FModified = true;
  451. }
  452. }
  453. //---------------------------------------------------------------------------
  454. void __fastcall TBookmarkList::ShortCuts(TShortCuts & ShortCuts)
  455. {
  456. for (int Index = 0; Index < Count; Index++)
  457. {
  458. TBookmark * Bookmark = Bookmarks[Index];
  459. if (Bookmark->ShortCut != 0)
  460. {
  461. ShortCuts.Add(Bookmark->ShortCut);
  462. }
  463. }
  464. }
  465. //---------------------------------------------------------------------------
  466. //---------------------------------------------------------------------------
  467. __fastcall TBookmark::TBookmark()
  468. {
  469. FOwner = NULL;
  470. }
  471. //---------------------------------------------------------------------------
  472. void __fastcall TBookmark::Assign(TPersistent * Source)
  473. {
  474. TBookmark * SourceBookmark;
  475. SourceBookmark = dynamic_cast<TBookmark *>(Source);
  476. if (SourceBookmark)
  477. {
  478. Name = SourceBookmark->Name;
  479. Local = SourceBookmark->Local;
  480. Remote = SourceBookmark->Remote;
  481. Node = SourceBookmark->Node;
  482. ShortCut = SourceBookmark->ShortCut;
  483. }
  484. else
  485. {
  486. TPersistent::Assign(Source);
  487. }
  488. }
  489. //---------------------------------------------------------------------------
  490. void __fastcall TBookmark::SetName(const UnicodeString value)
  491. {
  492. if (Name != value)
  493. {
  494. int OldIndex = FOwner ? FOwner->IndexOf(this) : -1;
  495. UnicodeString OldName = FName;
  496. FName = value;
  497. try
  498. {
  499. Modify(OldIndex);
  500. }
  501. catch(...)
  502. {
  503. FName = OldName;
  504. throw;
  505. }
  506. }
  507. }
  508. //---------------------------------------------------------------------------
  509. void __fastcall TBookmark::SetLocal(const UnicodeString value)
  510. {
  511. if (Local != value)
  512. {
  513. FLocal = value;
  514. Modify(-1);
  515. }
  516. }
  517. //---------------------------------------------------------------------------
  518. void __fastcall TBookmark::SetRemote(const UnicodeString value)
  519. {
  520. if (Remote != value)
  521. {
  522. FRemote = value;
  523. Modify(-1);
  524. }
  525. }
  526. //---------------------------------------------------------------------------
  527. void __fastcall TBookmark::SetNode(const UnicodeString value)
  528. {
  529. if (Node != value)
  530. {
  531. int OldIndex = FOwner ? FOwner->IndexOf(this) : -1;
  532. FNode = value;
  533. Modify(OldIndex);
  534. }
  535. }
  536. //---------------------------------------------------------------------------
  537. void __fastcall TBookmark::SetShortCut(TShortCut value)
  538. {
  539. if (ShortCut != value)
  540. {
  541. FShortCut = value;
  542. Modify(-1);
  543. }
  544. }
  545. //---------------------------------------------------------------------------
  546. void __fastcall TBookmark::Modify(int OldIndex)
  547. {
  548. if (FOwner)
  549. {
  550. FOwner->Modified = true;
  551. if (OldIndex >= 0)
  552. {
  553. FOwner->KeyChanged(OldIndex);
  554. }
  555. }
  556. }
  557. //---------------------------------------------------------------------------
  558. UnicodeString __fastcall TBookmark::BookmarkKey(const UnicodeString Node, const UnicodeString Name)
  559. {
  560. return FORMAT(L"%s\1%s", (Node, Name));
  561. }
  562. //---------------------------------------------------------------------------
  563. UnicodeString __fastcall TBookmark::GetKey()
  564. {
  565. return BookmarkKey(Node, Name);
  566. }
  567. //---------------------------------------------------------------------------
  568. UnicodeString __fastcall TBookmark::GetSideDirectory(TOperationSide Side)
  569. {
  570. return (Side == osLocal) ? Local : Remote;
  571. }