Bookmarks.cpp 17 KB

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