Bookmarks.cpp 17 KB

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