Bookmarks.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  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. DebugAssert(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 = FBookmarkLists->Strings[Index];
  166. Storage->RecursiveDeleteSubKey(Key);
  167. if (Storage->OpenSubKey(Key, true))
  168. {
  169. if (i < 3)
  170. {
  171. for (int IndexB = 0; IndexB < BookmarkList->Count; IndexB++)
  172. {
  173. TBookmark * Bookmark = BookmarkList->Bookmarks[IndexB];
  174. // avoid creating empty subfolder if there's no shortcut
  175. if ((i == 0) || (i == 1) ||
  176. ((i == 2) && (Bookmark->ShortCut != 0)))
  177. {
  178. bool HasNode = !Bookmark->Node.IsEmpty();
  179. if (!HasNode || Storage->OpenSubKey(Bookmark->Node, true))
  180. {
  181. switch (i)
  182. {
  183. case 0:
  184. Storage->WriteString(Bookmark->Name, Bookmark->Local);
  185. break;
  186. case 1:
  187. Storage->WriteString(Bookmark->Name, Bookmark->Remote);
  188. break;
  189. case 2:
  190. DebugAssert(Bookmark->ShortCut != 0);
  191. Storage->WriteInteger(Bookmark->Name, Bookmark->ShortCut);
  192. break;
  193. }
  194. if (HasNode)
  195. {
  196. Storage->CloseSubKey();
  197. }
  198. }
  199. }
  200. }
  201. }
  202. else
  203. {
  204. BookmarkList->SaveOptions(Storage);
  205. }
  206. Storage->CloseSubKey();
  207. }
  208. }
  209. }
  210. Storage->CloseSubKey();
  211. }
  212. }
  213. if (!All)
  214. {
  215. ModifyAll(false);
  216. }
  217. }
  218. //---------------------------------------------------------------------------
  219. void __fastcall TBookmarks::ModifyAll(bool Modify)
  220. {
  221. TBookmarkList * BookmarkList;
  222. for (int i = 0; i < FBookmarkLists->Count; i++)
  223. {
  224. BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[i]);
  225. DebugAssert(BookmarkList);
  226. BookmarkList->Modified = Modify;
  227. }
  228. }
  229. //---------------------------------------------------------------------------
  230. TBookmarkList * __fastcall TBookmarks::GetBookmarks(UnicodeString Index)
  231. {
  232. int I = FBookmarkLists->IndexOf(Index);
  233. if (I >= 0)
  234. {
  235. return dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[I]);
  236. }
  237. else
  238. {
  239. return NULL;
  240. }
  241. }
  242. //---------------------------------------------------------------------------
  243. void __fastcall TBookmarks::SetBookmarks(UnicodeString Index, TBookmarkList * value)
  244. {
  245. int I = FBookmarkLists->IndexOf(Index);
  246. if (I >= 0)
  247. {
  248. TBookmarkList * BookmarkList;
  249. BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[I]);
  250. BookmarkList->Assign(value);
  251. }
  252. else
  253. {
  254. TBookmarkList * BookmarkList = new TBookmarkList();
  255. BookmarkList->Assign(value);
  256. FBookmarkLists->AddObject(Index, BookmarkList);
  257. }
  258. }
  259. //---------------------------------------------------------------------------
  260. TBookmarkList * __fastcall TBookmarks::GetSharedBookmarks()
  261. {
  262. return GetBookmarks(FSharedKey);
  263. }
  264. //---------------------------------------------------------------------------
  265. void __fastcall TBookmarks::SetSharedBookmarks(TBookmarkList * value)
  266. {
  267. SetBookmarks(FSharedKey, value);
  268. }
  269. //---------------------------------------------------------------------------
  270. //---------------------------------------------------------------------------
  271. __fastcall TBookmarkList::TBookmarkList(): TPersistent()
  272. {
  273. FModified = false;
  274. FBookmarks = new TStringList();
  275. FBookmarks->CaseSensitive = false;
  276. FOpenedNodes = CreateSortedStringList();
  277. }
  278. //---------------------------------------------------------------------------
  279. __fastcall TBookmarkList::~TBookmarkList()
  280. {
  281. Clear();
  282. SAFE_DESTROY(FBookmarks);
  283. SAFE_DESTROY(FOpenedNodes);
  284. }
  285. //---------------------------------------------------------------------------
  286. void __fastcall TBookmarkList::Clear()
  287. {
  288. for (int i = 0; i < FBookmarks->Count; i++)
  289. {
  290. delete FBookmarks->Objects[i];
  291. }
  292. FBookmarks->Clear();
  293. FOpenedNodes->Clear();
  294. }
  295. //---------------------------------------------------------------------------
  296. void __fastcall TBookmarkList::Assign(TPersistent * Source)
  297. {
  298. TBookmarkList * SourceList;
  299. SourceList = dynamic_cast<TBookmarkList *>(Source);
  300. if (SourceList)
  301. {
  302. Clear();
  303. for (int i = 0; i < SourceList->FBookmarks->Count; i++)
  304. {
  305. TBookmark * Bookmark = new TBookmark();
  306. Bookmark->Assign(dynamic_cast<TBookmark *>(SourceList->FBookmarks->Objects[i]));
  307. Add(Bookmark);
  308. }
  309. FOpenedNodes->Assign(SourceList->FOpenedNodes);
  310. Modified = SourceList->Modified;
  311. }
  312. else
  313. {
  314. TPersistent::Assign(Source);
  315. }
  316. }
  317. //---------------------------------------------------------------------------
  318. void __fastcall TBookmarkList::LoadOptions(THierarchicalStorage * Storage)
  319. {
  320. FOpenedNodes->CommaText = Storage->ReadString(L"OpenedNodes", L"");
  321. }
  322. //---------------------------------------------------------------------------
  323. void __fastcall TBookmarkList::SaveOptions(THierarchicalStorage * Storage)
  324. {
  325. Storage->WriteString(L"OpenedNodes", FOpenedNodes->CommaText);
  326. }
  327. //---------------------------------------------------------------------------
  328. void __fastcall TBookmarkList::Add(TBookmark * Bookmark)
  329. {
  330. Insert(Count, Bookmark);
  331. }
  332. //---------------------------------------------------------------------------
  333. void __fastcall TBookmarkList::InsertBefore(TBookmark * BeforeBookmark, TBookmark * Bookmark)
  334. {
  335. DebugAssert(BeforeBookmark);
  336. int I = FBookmarks->IndexOf(BeforeBookmark->Key);
  337. DebugAssert(I >= 0);
  338. Insert(I, Bookmark);
  339. }
  340. //---------------------------------------------------------------------------
  341. void __fastcall TBookmarkList::MoveTo(TBookmark * ToBookmark,
  342. TBookmark * Bookmark, bool Before)
  343. {
  344. DebugAssert(ToBookmark != NULL);
  345. int NewIndex = FBookmarks->IndexOf(ToBookmark->Key);
  346. DebugAssert(Bookmark != NULL);
  347. int OldIndex = FBookmarks->IndexOf(Bookmark->Key);
  348. if (Before && (NewIndex > OldIndex))
  349. {
  350. // otherwise item is moved after the item in the target index
  351. NewIndex--;
  352. }
  353. else if (!Before && (NewIndex < OldIndex))
  354. {
  355. NewIndex++;
  356. }
  357. FModified = true;
  358. FBookmarks->Move(OldIndex, NewIndex);
  359. }
  360. //---------------------------------------------------------------------------
  361. void __fastcall TBookmarkList::Insert(int Index, TBookmark * Bookmark)
  362. {
  363. DebugAssert(Bookmark);
  364. DebugAssert(!Bookmark->FOwner);
  365. DebugAssert(!Bookmark->Name.IsEmpty());
  366. FModified = true;
  367. Bookmark->FOwner = this;
  368. if (FBookmarks->IndexOf(Bookmark->Key) >= 0)
  369. {
  370. throw Exception(FMTLOAD(DUPLICATE_BOOKMARK, (Bookmark->Name)));
  371. }
  372. FBookmarks->InsertObject(Index, Bookmark->Key, Bookmark);
  373. }
  374. //---------------------------------------------------------------------------
  375. void __fastcall TBookmarkList::Delete(TBookmark * Bookmark)
  376. {
  377. DebugAssert(Bookmark);
  378. DebugAssert(Bookmark->FOwner == this);
  379. int I = IndexOf(Bookmark);
  380. DebugAssert(I >= 0);
  381. FModified = true;
  382. Bookmark->FOwner = NULL;
  383. FBookmarks->Delete(I);
  384. delete Bookmark;
  385. }
  386. //---------------------------------------------------------------------------
  387. int __fastcall TBookmarkList::IndexOf(TBookmark * Bookmark)
  388. {
  389. return FBookmarks->IndexOf(Bookmark->Key);
  390. }
  391. //---------------------------------------------------------------------------
  392. void __fastcall TBookmarkList::KeyChanged(int Index)
  393. {
  394. DebugAssert(Index < Count);
  395. TBookmark * Bookmark = dynamic_cast<TBookmark *>(FBookmarks->Objects[Index]);
  396. DebugAssert(FBookmarks->Strings[Index] != Bookmark->Key);
  397. if (FBookmarks->IndexOf(Bookmark->Key) >= 0)
  398. {
  399. throw Exception(FMTLOAD(DUPLICATE_BOOKMARK, (Bookmark->Name)));
  400. }
  401. FBookmarks->Strings[Index] = Bookmark->Key;
  402. }
  403. //---------------------------------------------------------------------------
  404. TBookmark * __fastcall TBookmarkList::FindByName(const UnicodeString Node, const UnicodeString Name)
  405. {
  406. int I = FBookmarks->IndexOf(TBookmark::BookmarkKey(Node, Name));
  407. TBookmark * Bookmark = I >= 0 ? dynamic_cast<TBookmark *>(FBookmarks->Objects[I]) : NULL;
  408. DebugAssert(!Bookmark || (Bookmark->Node == Node && Bookmark->Name == Name));
  409. return Bookmark;
  410. }
  411. //---------------------------------------------------------------------------
  412. TBookmark * __fastcall TBookmarkList::FindByShortCut(TShortCut ShortCut)
  413. {
  414. for (int Index = 0; Index < FBookmarks->Count; Index++)
  415. {
  416. if (Bookmarks[Index]->ShortCut == ShortCut)
  417. {
  418. return Bookmarks[Index];
  419. }
  420. }
  421. return NULL;
  422. }
  423. //---------------------------------------------------------------------------
  424. int __fastcall TBookmarkList::GetCount()
  425. {
  426. return FBookmarks->Count;
  427. }
  428. //---------------------------------------------------------------------------
  429. TBookmark * __fastcall TBookmarkList::GetBookmarks(int Index)
  430. {
  431. TBookmark * Bookmark = dynamic_cast<TBookmark *>(FBookmarks->Objects[Index]);
  432. DebugAssert(Bookmark);
  433. return Bookmark;
  434. }
  435. //---------------------------------------------------------------------------
  436. bool __fastcall TBookmarkList::GetNodeOpened(UnicodeString Index)
  437. {
  438. return (FOpenedNodes->IndexOf(Index) >= 0);
  439. }
  440. //---------------------------------------------------------------------------
  441. void __fastcall TBookmarkList::SetNodeOpened(UnicodeString Index, bool value)
  442. {
  443. int I = FOpenedNodes->IndexOf(Index);
  444. if ((I >= 0) != value)
  445. {
  446. if (value)
  447. {
  448. FOpenedNodes->Add(Index);
  449. }
  450. else
  451. {
  452. FOpenedNodes->Delete(I);
  453. }
  454. FModified = true;
  455. }
  456. }
  457. //---------------------------------------------------------------------------
  458. void __fastcall TBookmarkList::ShortCuts(TShortCuts & ShortCuts)
  459. {
  460. for (int Index = 0; Index < Count; Index++)
  461. {
  462. TBookmark * Bookmark = Bookmarks[Index];
  463. if (Bookmark->ShortCut != 0)
  464. {
  465. ShortCuts.Add(Bookmark->ShortCut);
  466. }
  467. }
  468. }
  469. //---------------------------------------------------------------------------
  470. //---------------------------------------------------------------------------
  471. __fastcall TBookmark::TBookmark()
  472. {
  473. FOwner = NULL;
  474. }
  475. //---------------------------------------------------------------------------
  476. void __fastcall TBookmark::Assign(TPersistent * Source)
  477. {
  478. TBookmark * SourceBookmark;
  479. SourceBookmark = dynamic_cast<TBookmark *>(Source);
  480. if (SourceBookmark)
  481. {
  482. Name = SourceBookmark->Name;
  483. Local = SourceBookmark->Local;
  484. Remote = SourceBookmark->Remote;
  485. Node = SourceBookmark->Node;
  486. ShortCut = SourceBookmark->ShortCut;
  487. }
  488. else
  489. {
  490. TPersistent::Assign(Source);
  491. }
  492. }
  493. //---------------------------------------------------------------------------
  494. void __fastcall TBookmark::SetName(const UnicodeString value)
  495. {
  496. if (Name != value)
  497. {
  498. int OldIndex = FOwner ? FOwner->IndexOf(this) : -1;
  499. UnicodeString OldName = FName;
  500. FName = value;
  501. try
  502. {
  503. Modify(OldIndex);
  504. }
  505. catch(...)
  506. {
  507. FName = OldName;
  508. throw;
  509. }
  510. }
  511. }
  512. //---------------------------------------------------------------------------
  513. void __fastcall TBookmark::SetLocal(const UnicodeString value)
  514. {
  515. if (Local != value)
  516. {
  517. FLocal = value;
  518. Modify(-1);
  519. }
  520. }
  521. //---------------------------------------------------------------------------
  522. void __fastcall TBookmark::SetRemote(const UnicodeString value)
  523. {
  524. if (Remote != value)
  525. {
  526. FRemote = value;
  527. Modify(-1);
  528. }
  529. }
  530. //---------------------------------------------------------------------------
  531. void __fastcall TBookmark::SetNode(const UnicodeString value)
  532. {
  533. if (Node != value)
  534. {
  535. int OldIndex = FOwner ? FOwner->IndexOf(this) : -1;
  536. FNode = value;
  537. Modify(OldIndex);
  538. }
  539. }
  540. //---------------------------------------------------------------------------
  541. void __fastcall TBookmark::SetShortCut(TShortCut value)
  542. {
  543. if (ShortCut != value)
  544. {
  545. FShortCut = value;
  546. Modify(-1);
  547. }
  548. }
  549. //---------------------------------------------------------------------------
  550. void __fastcall TBookmark::Modify(int OldIndex)
  551. {
  552. if (FOwner)
  553. {
  554. FOwner->Modified = true;
  555. if (OldIndex >= 0)
  556. {
  557. FOwner->KeyChanged(OldIndex);
  558. }
  559. }
  560. }
  561. //---------------------------------------------------------------------------
  562. UnicodeString __fastcall TBookmark::BookmarkKey(const UnicodeString Node, const UnicodeString Name)
  563. {
  564. return FORMAT(L"%s\1%s", (Node, Name));
  565. }
  566. //---------------------------------------------------------------------------
  567. UnicodeString __fastcall TBookmark::GetKey()
  568. {
  569. return BookmarkKey(Node, Name);
  570. }
  571. //---------------------------------------------------------------------------
  572. UnicodeString __fastcall TBookmark::GetSideDirectory(TOperationSide Side)
  573. {
  574. return (Side == osLocal) ? Local : Remote;
  575. }