summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-09-25 09:01:41 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-09-25 09:01:41 +0300
commit242e8231ea61278fe482020658be86c2dec0ae53 (patch)
treebb88541f9f808cb5a3af769fe265439341e97237
parented2c4a872dbddd2eaa13b280543ffabb0d197851 (diff)
Persistent bookmark folder state
Incremented the version of state.lgr so it can include bookmark folder open/closed state for each of the two/four sidebars.
-rw-r--r--src/app.c12
-rw-r--r--src/defs.h3
-rw-r--r--src/ui/sidebarwidget.c31
-rw-r--r--src/ui/sidebarwidget.h6
-rw-r--r--src/ui/window.c10
5 files changed, 50 insertions, 12 deletions
diff --git a/src/app.c b/src/app.c
index 2f4b4fb8..2bad3cb6 100644
--- a/src/app.c
+++ b/src/app.c
@@ -425,12 +425,22 @@ static iBool loadState_App_(iApp *d) {
425 readf_Stream(stream_File(f)), 425 readf_Stream(stream_File(f)),
426 readf_Stream(stream_File(f)) 426 readf_Stream(stream_File(f))
427 }; 427 };
428 iIntSet *closedFolders[2] = {
429 collectNew_IntSet(),
430 collectNew_IntSet()
431 };
432 if (version >= bookmarkFolderState_FileVersion) {
433 deserialize_IntSet(closedFolders[0], stream_File(f));
434 deserialize_IntSet(closedFolders[1], stream_File(f));
435 }
428 const uint8_t rootIndex = bits & 0xff; 436 const uint8_t rootIndex = bits & 0xff;
429 const uint8_t flags = bits >> 8; 437 const uint8_t flags = bits >> 8;
430 iRoot *root = d->window->base.roots[rootIndex]; 438 iRoot *root = d->window->base.roots[rootIndex];
431 if (root) { 439 if (root) {
432 iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); 440 iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar");
433 iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2"); 441 iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2");
442 setClosedFolders_SidebarWidget(sidebar, closedFolders[0]);
443 setClosedFolders_SidebarWidget(sidebar2, closedFolders[1]);
434 postCommandf_Root(root, "sidebar.mode arg:%u", modes & 0xf); 444 postCommandf_Root(root, "sidebar.mode arg:%u", modes & 0xf);
435 postCommandf_Root(root, "sidebar2.mode arg:%u", modes >> 4); 445 postCommandf_Root(root, "sidebar2.mode arg:%u", modes >> 4);
436 if (deviceType_App() != phone_AppDeviceType) { 446 if (deviceType_App() != phone_AppDeviceType) {
@@ -513,6 +523,8 @@ static void saveState_App_(const iApp *d) {
513 (mode_SidebarWidget(sidebar2) << 4)); 523 (mode_SidebarWidget(sidebar2) << 4));
514 writef_Stream(stream_File(f), width_SidebarWidget(sidebar)); 524 writef_Stream(stream_File(f), width_SidebarWidget(sidebar));
515 writef_Stream(stream_File(f), width_SidebarWidget(sidebar2)); 525 writef_Stream(stream_File(f), width_SidebarWidget(sidebar2));
526 serialize_IntSet(closedFolders_SidebarWidget(sidebar), stream_File(f));
527 serialize_IntSet(closedFolders_SidebarWidget(sidebar2), stream_File(f));
516 } 528 }
517 } 529 }
518 } 530 }
diff --git a/src/defs.h b/src/defs.h
index a81d57f1..e1c0a125 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -36,9 +36,10 @@ enum iFileVersion {
36 multipleRoots_FileVersion = 2, 36 multipleRoots_FileVersion = 2,
37 serializedSidebarState_FileVersion = 3, 37 serializedSidebarState_FileVersion = 3,
38 addedRecentUrlFlags_FileVersion = 4, 38 addedRecentUrlFlags_FileVersion = 4,
39 bookmarkFolderState_FileVersion = 5,
39 /* meta */ 40 /* meta */
40 idents_FileVersion = 1, /* version used by GmCerts/idents.lgr */ 41 idents_FileVersion = 1, /* version used by GmCerts/idents.lgr */
41 latest_FileVersion = 4, 42 latest_FileVersion = 5,
42}; 43};
43 44
44enum iImageStyle { 45enum iImageStyle {
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 8e38dcb8..3018f16d 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -108,7 +108,7 @@ struct Impl_SidebarWidget {
108 iWidget * menu; 108 iWidget * menu;
109 iSidebarItem * contextItem; /* list item accessed in the context menu */ 109 iSidebarItem * contextItem; /* list item accessed in the context menu */
110 size_t contextIndex; /* index of list item accessed in the context menu */ 110 size_t contextIndex; /* index of list item accessed in the context menu */
111 iIntSet closedFolders; /* otherwise open */ 111 iIntSet * closedFolders; /* otherwise open */
112}; 112};
113 113
114iDefineObjectConstructionArgs(SidebarWidget, (enum iSidebarSide side), side) 114iDefineObjectConstructionArgs(SidebarWidget, (enum iSidebarSide side), side)
@@ -255,7 +255,7 @@ static void updateContextMenu_SidebarWidget_(iSidebarWidget *d) {
255 255
256static iBool isBookmarkFolded_SidebarWidget_(const iSidebarWidget *d, const iBookmark *bm) { 256static iBool isBookmarkFolded_SidebarWidget_(const iSidebarWidget *d, const iBookmark *bm) {
257 while (bm->parentId) { 257 while (bm->parentId) {
258 if (contains_IntSet(&d->closedFolders, bm->parentId)) { 258 if (contains_IntSet(d->closedFolders, bm->parentId)) {
259 return iTrue; 259 return iTrue;
260 } 260 }
261 bm = get_Bookmarks(bookmarks_App(), bm->parentId); 261 bm = get_Bookmarks(bookmarks_App(), bm->parentId);
@@ -397,7 +397,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
397 item->id = id_Bookmark(bm); 397 item->id = id_Bookmark(bm);
398 item->indent = depth_Bookmark(bm); 398 item->indent = depth_Bookmark(bm);
399 if (isFolder_Bookmark(bm)) { 399 if (isFolder_Bookmark(bm)) {
400 item->icon = contains_IntSet(&d->closedFolders, item->id) ? 0x27e9 : 0xfe40; 400 item->icon = contains_IntSet(d->closedFolders, item->id) ? 0x27e9 : 0xfe40;
401 } 401 }
402 else { 402 else {
403 item->icon = bm->icon; 403 item->icon = bm->icon;
@@ -655,6 +655,11 @@ iBool setMode_SidebarWidget(iSidebarWidget *d, enum iSidebarMode mode) {
655 return iTrue; 655 return iTrue;
656} 656}
657 657
658void setClosedFolders_SidebarWidget(iSidebarWidget *d, const iIntSet *closedFolders) {
659 delete_IntSet(d->closedFolders);
660 d->closedFolders = copy_IntSet(closedFolders);
661}
662
658enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) { 663enum iSidebarMode mode_SidebarWidget(const iSidebarWidget *d) {
659 return d ? d->mode : 0; 664 return d ? d->mode : 0;
660} 665}
@@ -663,6 +668,10 @@ float width_SidebarWidget(const iSidebarWidget *d) {
663 return d ? d->widthAsGaps : 0; 668 return d ? d->widthAsGaps : 0;
664} 669}
665 670
671const iIntSet *closedFolders_SidebarWidget(const iSidebarWidget *d) {
672 return d->closedFolders;
673}
674
666static const char *normalModeLabels_[max_SidebarMode] = { 675static const char *normalModeLabels_[max_SidebarMode] = {
667 book_Icon " ${sidebar.bookmarks}", 676 book_Icon " ${sidebar.bookmarks}",
668 star_Icon " ${sidebar.feeds}", 677 star_Icon " ${sidebar.feeds}",
@@ -736,7 +745,7 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) {
736 d->resizer = NULL; 745 d->resizer = NULL;
737 d->list = NULL; 746 d->list = NULL;
738 d->actions = NULL; 747 d->actions = NULL;
739 init_IntSet(&d->closedFolders); 748 d->closedFolders = new_IntSet();
740 /* On a phone, the right sidebar is used exclusively for Identities. */ 749 /* On a phone, the right sidebar is used exclusively for Identities. */
741 const iBool isPhone = deviceType_App() == phone_AppDeviceType; 750 const iBool isPhone = deviceType_App() == phone_AppDeviceType;
742 if (!isPhone || d->side == left_SidebarSide) { 751 if (!isPhone || d->side == left_SidebarSide) {
@@ -820,7 +829,7 @@ void init_SidebarWidget(iSidebarWidget *d, enum iSidebarSide side) {
820 829
821void deinit_SidebarWidget(iSidebarWidget *d) { 830void deinit_SidebarWidget(iSidebarWidget *d) {
822 deinit_String(&d->cmdPrefix); 831 deinit_String(&d->cmdPrefix);
823 deinit_IntSet(&d->closedFolders); 832 delete_IntSet(d->closedFolders);
824} 833}
825 834
826iBool setButtonFont_SidebarWidget(iSidebarWidget *d, int font) { 835iBool setButtonFont_SidebarWidget(iSidebarWidget *d, int font) {
@@ -869,11 +878,11 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, si
869 } 878 }
870 case bookmarks_SidebarMode: 879 case bookmarks_SidebarMode:
871 if (isEmpty_String(&item->url)) /* a folder */ { 880 if (isEmpty_String(&item->url)) /* a folder */ {
872 if (contains_IntSet(&d->closedFolders, item->id)) { 881 if (contains_IntSet(d->closedFolders, item->id)) {
873 remove_IntSet(&d->closedFolders, item->id); 882 remove_IntSet(d->closedFolders, item->id);
874 } 883 }
875 else { 884 else {
876 insert_IntSet(&d->closedFolders, item->id); 885 insert_IntSet(d->closedFolders, item->id);
877 } 886 }
878 updateItems_SidebarWidget_(d); 887 updateItems_SidebarWidget_(d);
879 break; 888 break;
@@ -956,8 +965,8 @@ void setWidth_SidebarWidget(iSidebarWidget *d, float widthAsGaps) {
956 int width = widthAsGaps * gap_UI; /* in pixels */ 965 int width = widthAsGaps * gap_UI; /* in pixels */
957 if (!isFixedWidth) { 966 if (!isFixedWidth) {
958 /* Even less space if the other sidebar is visible, too. */ 967 /* Even less space if the other sidebar is visible, too. */
959 const int otherWidth = 968 const iWidget *other = findWidget_App(d->side == left_SidebarSide ? "sidebar2" : "sidebar");
960 width_Widget(findWidget_App(d->side == left_SidebarSide ? "sidebar2" : "sidebar")); 969 const int otherWidth = isVisible_Widget(other) ? width_Widget(other) : 0;
961 width = iClamp(width, 30 * gap_UI, size_Root(w->root).x - 50 * gap_UI - otherWidth); 970 width = iClamp(width, 30 * gap_UI, size_Root(w->root).x - 50 * gap_UI - otherWidth);
962 } 971 }
963 d->widthAsGaps = (float) width / (float) gap_UI; 972 d->widthAsGaps = (float) width / (float) gap_UI;
@@ -1328,6 +1337,8 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1328 if (isFolder_Bookmark(bm)) { 1337 if (isFolder_Bookmark(bm)) {
1329 const iPtrArray *list = list_Bookmarks(bookmarks_App(), NULL, 1338 const iPtrArray *list = list_Bookmarks(bookmarks_App(), NULL,
1330 filterInsideFolder_Bookmark, bm); 1339 filterInsideFolder_Bookmark, bm);
1340 /* Folder deletion requires confirmation because folders can contain
1341 any number of bookmarks and other folders. */
1331 if (argLabel_Command(cmd, "confirmed") || isEmpty_PtrArray(list)) { 1342 if (argLabel_Command(cmd, "confirmed") || isEmpty_PtrArray(list)) {
1332 iConstForEach(PtrArray, i, list) { 1343 iConstForEach(PtrArray, i, list) {
1333 removeEntries_Feeds(id_Bookmark(i.ptr)); 1344 removeEntries_Feeds(id_Bookmark(i.ptr));
diff --git a/src/ui/sidebarwidget.h b/src/ui/sidebarwidget.h
index 2894a951..638a1f2f 100644
--- a/src/ui/sidebarwidget.h
+++ b/src/ui/sidebarwidget.h
@@ -24,6 +24,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
24 24
25#include "widget.h" 25#include "widget.h"
26 26
27#include <the_Foundation/intset.h>
28
27enum iSidebarMode { 29enum iSidebarMode {
28 bookmarks_SidebarMode, 30 bookmarks_SidebarMode,
29 feeds_SidebarMode, 31 feeds_SidebarMode,
@@ -49,8 +51,10 @@ iDeclareWidgetClass(SidebarWidget)
49iDeclareObjectConstructionArgs(SidebarWidget, enum iSidebarSide side) 51iDeclareObjectConstructionArgs(SidebarWidget, enum iSidebarSide side)
50 52
51iBool setMode_SidebarWidget (iSidebarWidget *, enum iSidebarMode mode); 53iBool setMode_SidebarWidget (iSidebarWidget *, enum iSidebarMode mode);
54void setWidth_SidebarWidget (iSidebarWidget *, float widthAsGaps);
52iBool setButtonFont_SidebarWidget (iSidebarWidget *, int font); 55iBool setButtonFont_SidebarWidget (iSidebarWidget *, int font);
56void setClosedFolders_SidebarWidget (iSidebarWidget *, const iIntSet *closedFolders);
53 57
54enum iSidebarMode mode_SidebarWidget (const iSidebarWidget *); 58enum iSidebarMode mode_SidebarWidget (const iSidebarWidget *);
55float width_SidebarWidget (const iSidebarWidget *); 59float width_SidebarWidget (const iSidebarWidget *);
56void setWidth_SidebarWidget (iSidebarWidget *, float widthAsGaps); 60const iIntSet * closedFolders_SidebarWidget (const iSidebarWidget *);
diff --git a/src/ui/window.c b/src/ui/window.c
index 5941ef5f..066ea102 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
30#include "keys.h" 30#include "keys.h"
31#include "labelwidget.h" 31#include "labelwidget.h"
32#include "documentwidget.h" 32#include "documentwidget.h"
33#include "sidebarwidget.h"
33#include "paint.h" 34#include "paint.h"
34#include "root.h" 35#include "root.h"
35#include "touch.h" 36#include "touch.h"
@@ -1421,6 +1422,15 @@ void setSplitMode_MainWindow(iMainWindow *d, int splitFlags) {
1421 w->keyRoot->window = w; 1422 w->keyRoot->window = w;
1422 setCurrent_Root(w->roots[newRootIndex]); 1423 setCurrent_Root(w->roots[newRootIndex]);
1423 createUserInterface_Root(w->roots[newRootIndex]); 1424 createUserInterface_Root(w->roots[newRootIndex]);
1425 /* Bookmark folder state will match the old root's state. */ {
1426 for (int sb = 0; sb < 2; sb++) {
1427 const char *sbId = (sb == 0 ? "sidebar" : "sidebar2");
1428 setClosedFolders_SidebarWidget(
1429 findChild_Widget(w->roots[newRootIndex]->widget, sbId),
1430 closedFolders_SidebarWidget(
1431 findChild_Widget(w->roots[newRootIndex ^ 1]->widget, sbId)));
1432 }
1433 }
1424 if (!isEmpty_String(d->pendingSplitUrl)) { 1434 if (!isEmpty_String(d->pendingSplitUrl)) {
1425 postCommandf_Root(w->roots[newRootIndex], "open url:%s", 1435 postCommandf_Root(w->roots[newRootIndex], "open url:%s",
1426 cstr_String(d->pendingSplitUrl)); 1436 cstr_String(d->pendingSplitUrl));