]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Open all bookmarks in a folder on long-press. https://redmine.stoutner.com/issues/926
authorSoren Stoutner <soren@stoutner.com>
Mon, 5 Dec 2022 22:25:35 +0000 (15:25 -0700)
committerSoren Stoutner <soren@stoutner.com>
Mon, 5 Dec 2022 22:25:35 +0000 (15:25 -0700)
app/src/main/assets/de/guide_interface.html
app/src/main/assets/en/guide_interface.html
app/src/main/assets/es/guide_interface.html
app/src/main/assets/fr/guide_interface.html
app/src/main/assets/it/guide_interface.html
app/src/main/assets/pt-rBR/guide_interface.html
app/src/main/assets/ru/guide_interface.html
app/src/main/assets/tr/guide_interface.html
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.kt

index 3ac4cb98df79415711cacafa4167a9f4385be474..95d00dda4d821cb6edfb59733458348164c64ef1 100644 (file)
@@ -36,7 +36,7 @@
             <a href="https://redmine.stoutner.com/boards/1/topics/243">bis das Menü angezeigt wird</a> und wischen dann, um es zu öffnen.
             Auf manchen Geräten mit abgerundeten Kanten kann das Ausklappen des Menüs schwierig sein. Daher kann das Lesezeichen-Menü auch über das Options-Menü geöffnet werden.</p>
 
-        <p>Kurzes Antippen eines Lesezeichens öffnet dieses im aktuellen Tab, langes Drücken öffnet es in einem neuen Tab.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             Durch Antippen des obersten Symbols im Lesezeichen-Menü können abgespeicherte Lesezeichen bearbeitet und umgeordnet werden.</p>
     </body>
 </html>
index 0f3bf03cf8ee2286244e85dd8e2c9f11e969d270..7b417a81b13de9daafc72b13cd5e4549c73974e0 100644 (file)
@@ -34,7 +34,7 @@
             the drawer may be opened by long-pressing on the edge of the screen <a href="https://redmine.stoutner.com/boards/1/topics/243">until the drawer peaks out</a> and then swiping it open.
             Sometimes it can be difficult to get the bookmarks drawer to reliably peak on devices with curved edges, so it is also possible to open the bookmarks drawer from the options menu.</p>
 
-        <p>Tapping on a bookmark opens it in the current tab and long-pressing on a bookmark opens it in a new tab.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             Tapping the top floating action button in the bookmarks drawer opens the bookmarks activity, where bookmarks can be edited and reorganized.</p>
     </body>
 </html>
index 47dd1e8b81b1d21dff9310e597e665f73fb0cd82..0cd63d483ebcc8efbbd2b7599be99f335c6f9e53 100644 (file)
@@ -37,7 +37,7 @@
             A veces puede ser difícil conseguir que el cajón de marcadores llegue a su punto máximo de forma fiable en dispositivos con bordes curvos,
             por lo que también es posible abrir el cajón de marcadores desde el menú de opciones.</p>
 
-        <p>Al tocar un marcador se abre en la pestaña actual y al pulsar prolongadamente sobre un marcador se abre en una nueva pestaña.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             Al tocar el botón de acción superior flotante en el cajón de marcadores se abre la actividad de marcadores, donde se pueden editar y reorganizar los marcadores.</p>
     </body>
 </html>
index b2a61b7d2d6c64b4d4100e077089715c329284ab..76625e1c56791b6738a8efb22558b5faf57e4b6a 100644 (file)
@@ -38,7 +38,7 @@
             Il est parfois difficile de faire apparaître le gestionnaire de favoris de manière fiable sur les appareils aux bords incurvés,
             c'est pourquoi il est également possible d'ouvrir le gestionnaire de favoris à partir du menu des options.</p>
 
-        <p>Le fait d'appuyer sur un favori l'ouvre dans l'onglet actuel et le fait d'appuyer longuement sur un favori l'ouvre dans un nouvel onglet.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             Si vous appuyez sur le bouton d'action flottant supérieur dans le gestionnaire de favoris, vous ouvrez un volet dans lequel vous pouvez modifier et réorganiser les favoris.</p>
     </body>
 </html>
index b3bfab9cb5271687eaceec03524e4bf2eb4c0e2f..f6c736c99abdc63e08629cc5b5be5d9d18395cbb 100644 (file)
@@ -36,7 +36,7 @@
             il cassetto può essere aperto anche tenendo premuto il bordo dello schermo <a href="https://redmine.stoutner.com/boards/1/topics/243">finchè appare il cassetto</a> e quindi scorrendo per aprirlo.
             A volte può risultare difficile fare in modo che il cassetto dei segnalibri appaia sui dispositivi con i bordi incurvati per cui è possibile aprirlo anche dal menù delle opzioni.</p>
 
-        <p>Selezionando un segnalibro, viene aperto nella scheda corrente, mentre tenendolo premuto si apre in una nuova scheda.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             Se si tocca il pulsante flottante più in alto nel cassetto dei segnalibri viene aperta la scheda dei segnalibri dove è possibile modificarli e riordinarli.</p>
     </body>
 </html>
index 3afad7b1e866f56c9d5710afe56f66b9fff6b198..094c0c7cbe1336adc4ec148353c43c5f44e04d87 100644 (file)
@@ -36,7 +36,7 @@
             the drawer may be opened by long-pressing on the edge of the screen <a href="https://redmine.stoutner.com/boards/1/topics/243">until the drawer peaks out</a> and then swiping it open.
             Sometimes it can be difficult to get the bookmarks drawer to reliably peak on devices with curved edges, so it is also possible to open the bookmarks drawer from the options menu.</p>
 
-        <p>Tapping on a bookmark opens it in the current tab and long-pressing on a bookmark opens it in a new tab.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             Tapping the top floating action button in the bookmarks drawer opens the bookmarks activity, where bookmarks can be edited and reorganized.</p>
     </body>
 </html>
index 4c7104f87f229a62c47d38e82f4c3ef60a5ab28b..eaaf3e8e7763313dcf8665c3886033af9e52febe 100644 (file)
@@ -34,7 +34,7 @@
             панель можно открыть длительным нажатием на край экрана <a href="https://redmine.stoutner.com/boards/1/topics/243">до ее появления</a>, а затем смахнув.
             На устройствах с изогнутыми краями иногда бывает непросто добиться появления панели закладок, поэтому можно открыть ее из меню параметров.</p>
 
-        <p>При нажатии на закладку она открывается на текущей вкладке, а при длительном нажатии - на новой вкладке.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             При нажатии верхней кнопки действия в панели закладок открывается страница действий с закладками, где их можно редактировать и упорядочивать.</p>
     </body>
 </html>
index 0f3bf03cf8ee2286244e85dd8e2c9f11e969d270..7b417a81b13de9daafc72b13cd5e4549c73974e0 100644 (file)
@@ -34,7 +34,7 @@
             the drawer may be opened by long-pressing on the edge of the screen <a href="https://redmine.stoutner.com/boards/1/topics/243">until the drawer peaks out</a> and then swiping it open.
             Sometimes it can be difficult to get the bookmarks drawer to reliably peak on devices with curved edges, so it is also possible to open the bookmarks drawer from the options menu.</p>
 
-        <p>Tapping on a bookmark opens it in the current tab and long-pressing on a bookmark opens it in a new tab.
+        <p>Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs.
             Tapping the top floating action button in the bookmarks drawer opens the bookmarks activity, where bookmarks can be edited and reorganized.</p>
     </body>
 </html>
index c0812d0c14bd9bdbc4902263ae717035797c2dba..3d0013e409d6c62d8c60b631b50f8d9ceaf3e52d 100644 (file)
@@ -3425,14 +3425,26 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             // Check to see if the bookmark is a folder.
             if (isFolder) {  // The bookmark is a folder.
-                // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`.
-                oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                // Get a cursor of all the bookmarks in the folder.
+                Cursor bookmarksCursor = bookmarksDatabaseHelper.getFolderBookmarks(databaseId);
 
-                // Instantiate the edit folder bookmark dialog.
-                DialogFragment editBookmarkFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon());
+                // Move to the first entry in the cursor.
+                bookmarksCursor.moveToFirst();
 
-                // Show the edit folder bookmark dialog.
-                editBookmarkFolderDialog.show(getSupportFragmentManager(), getString(R.string.edit_folder));
+                // Open each bookmark
+                for (int i = 0; i < bookmarksCursor.getCount(); i++) {
+                    // Load the bookmark in a new tab, moving to the tab for the first bookmark (i == 0).
+                    addNewTab(bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), (i == 0));
+
+                    // Move to the next bookmark.
+                    bookmarksCursor.moveToNext();
+                }
+
+                // Close the cursor.
+                bookmarksCursor.close();
+
+                // Close the bookmarks drawer.
+                drawerLayout.closeDrawer(GravityCompat.END);
             } else {  // The bookmark is not a folder.
                 // Get the bookmark cursor for this ID.
                 Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseId);
@@ -3443,6 +3455,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Load the bookmark in a new tab.
                 addNewTab(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), true);
 
+                // Close the cursor.
+                bookmarkCursor.close();
+
                 // Close the bookmarks drawer.
                 drawerLayout.closeDrawer(GravityCompat.END);
             }
index 8804e997cf53c14f8d5a23a560ab76d43594eb5b..bd90abceadc153643175632479e4299a14de67f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2022 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -65,6 +65,36 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
         // Code for upgrading the database will be added here when the schema version > 1.
     }
 
+    // Get a cursor of all the folders.
+    val allFolders: Cursor
+        get() {
+            // Get a readable database handle.
+            val bookmarksDatabase = this.readableDatabase
+
+            // Return the cursor with the all the folders.  The cursor cannot be closed because it is used in the parent activity.
+            return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 ORDER BY $BOOKMARK_NAME ASC", null)
+        }
+
+    // Get a cursor for all bookmarks and folders.
+    val allBookmarks: Cursor
+        get() {
+            // Get a readable database handle.
+            val bookmarksDatabase = this.readableDatabase
+
+            // Return a cursor with the entire contents of the bookmarks table.  The cursor cannot be closed because it is used in the parent activity.
+            return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE", null)
+        }
+
+    // Get a cursor for all bookmarks and folders ordered by display order.
+    val allBookmarksByDisplayOrder: Cursor
+        get() {
+            // Get a readable database handle.
+            val bookmarksDatabase = this.readableDatabase
+
+            // Return a cursor with the entire contents of the bookmarks table ordered by the display order.  The cursor cannot be closed because it is used in the parent activity.
+            return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE ORDER BY $DISPLAY_ORDER ASC", null)
+        }
+
     // Create a bookmark.
     fun createBookmark(bookmarkName: String, bookmarkURL: String, parentFolder: String, displayOrder: Int, favoriteIcon: ByteArray) {
         // Store the bookmark data in a content values.
@@ -122,6 +152,18 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
         bookmarksDatabase.close()
     }
 
+    // Delete one bookmark.
+    fun deleteBookmark(databaseId: Int) {
+        // Get a writable database handle.
+        val bookmarksDatabase = this.writableDatabase
+
+        // Deletes the row with the given database ID.
+        bookmarksDatabase.delete(BOOKMARKS_TABLE, "$ID = $databaseId", null)
+
+        // Close the database handle.
+        bookmarksDatabase.close()
+    }
+
     // Get a cursor for the bookmark with the specified database ID.
     fun getBookmark(databaseId: Int): Cursor {
         // Get a readable database handle.
@@ -131,165 +173,92 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
         return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
     }
 
-    // Get the folder name for the specified database ID.
-    fun getFolderName(databaseId: Int): String {
+    // Get a cursor for all bookmarks and folders by display order except those with the specified IDs.
+    fun getAllBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
-        // Get the cursor for the folder with the specified database ID.
-        val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
-
-        // Move to the first record.
-        folderCursor.moveToFirst()
+        // Prepare a string builder to contain the comma-separated list of IDs not to get.
+        val idsNotToGetStringBuilder = StringBuilder()
 
-        // Get the folder name.
-        val folderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BOOKMARK_NAME))
+        // Extract the array of IDs not to get to the string builder.
+        for (databaseIdLong in exceptIdLongArray) {
+            // Check to see if there is already a number in the builder.
+            if (idsNotToGetStringBuilder.isNotEmpty()) {
+                // This is not the first number, so place a `,` before the new number.
+                idsNotToGetStringBuilder.append(",")
+            }
 
-        // Close the cursor and the database handle.
-        folderCursor.close()
-        bookmarksDatabase.close()
+            // Add the new number to the builder.
+            idsNotToGetStringBuilder.append(databaseIdLong)
+        }
 
-        // Return the folder name.
-        return folderName
+        // Return a cursor with all the bookmarks except those specified ordered by display order.  The cursor cannot be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC", null)
     }
 
-    // Get the database ID for the specified folder name.
-    fun getFolderDatabaseId(folderName: String): Int {
+    // Get a cursor for all bookmarks and folders except those with the specified IDs.
+    fun getAllBookmarksExcept(exceptIdLongArray: LongArray): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
-        // SQL escape the folder name.
-        val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
-
-        // Get the cursor for the folder with the specified name.
-        val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null)
-
-        // Move to the first record.
-        folderCursor.moveToFirst()
+        // Prepare a string builder to contain the comma-separated list of IDs not to get.
+        val idsNotToGetStringBuilder = StringBuilder()
 
-        // Get the database ID.
-        val databaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(ID))
+        // Extract the array of IDs not to get to the string builder.
+        for (databaseIdLong in exceptIdLongArray) {
+            // Check to see if there is already a number in the builder.
+            if (idsNotToGetStringBuilder.isNotEmpty()) {
+                // This is not the first number, so place a `,` before the new number.
+                idsNotToGetStringBuilder.append(",")
+            }
 
-        // Close the cursor and the database handle.
-        folderCursor.close()
-        bookmarksDatabase.close()
+            // Add the new number to the builder.
+            idsNotToGetStringBuilder.append(databaseIdLong)
+        }
 
-        // Return the database ID.
-        return databaseId
+        // Return a cursor with all the bookmarks except those specified.  The cursor cannot be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder)", null)
     }
 
-    // Get a cursor for the specified folder name.
-    fun getFolder(folderName: String): Cursor {
+    // Get a cursor with just database ID of bookmarks and folders in the specified folder.  This is useful for deleting folders with bookmarks that have favorite icons too large to fit in a cursor.
+    fun getBookmarkIds(folderName: String): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
         // SQL escape the folder name.
         val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
 
-        // Return the cursor for the specified folder.  The cursor can't be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null)
-    }
-
-    // Get a cursor of all the folders except those specified.
-    fun getFoldersExcept(exceptFolders: String): Cursor {
-        // Get a readable database handle.
-        val bookmarksDatabase = this.readableDatabase
-
-        // Return the cursor of all folders except those specified.  Each individual folder in the list has already been SQL escaped.  The cursor can't be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME NOT IN ($exceptFolders) ORDER BY $BOOKMARK_NAME ASC", null)
-    }
-
-    // Get a cursor with all the subfolders of the specified folder.
-    fun getSubfolders(currentFolder: String): Cursor {
-        // Get a readable database handle.
-        val bookmarksDatabase = this.readableDatabase
-
-        // SQL escape the current folder.
-        val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder)
-
-        // Return the cursor with the subfolders.  The cursor can't be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedCurrentFolder AND $IS_FOLDER = 1", null)
+        // Return a cursor with all the database IDs.  The cursor cannot be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT $ID FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null)
     }
 
-    // Get the name of the parent folder.
-    fun getParentFolderName(currentFolder: String): String {
+    // Get a cursor for bookmarks and folders in the specified folder.
+    fun getBookmarks(folderName: String): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
-        // SQL escape the current folder.
-        val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder)
-
-        // Get a cursor for the current folder.
-        val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME = $sqlEscapedCurrentFolder", null)
-
-        // Move to the first record.
-        bookmarkCursor.moveToFirst()
-
-        // Store the name of the parent folder.
-        val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER))
-
-        // Close the cursor and the database.
-        bookmarkCursor.close()
-        bookmarksDatabase.close()
+        // SQL escape the folder name.
+        val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
 
-        // Return the parent folder string.
-        return parentFolder
+        // Return a cursor with all the bookmarks in a specified folder.  The cursor cannot be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null)
     }
 
-    // Get the name of the parent folder.
-    fun getParentFolderName(databaseId: Int): String {
+    // Get a cursor for bookmarks and folders in the specified folder ordered by display order.
+    fun getBookmarksByDisplayOrder(folderName: String): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
-        // Get a cursor for the specified database ID.
-        val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
-
-        // Move to the first record.
-        bookmarkCursor.moveToFirst()
-
-        // Store the name of the parent folder.
-        val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER))
-
-        // Close the cursor and the database.
-        bookmarkCursor.close()
-        bookmarksDatabase.close()
+        // SQL escape the folder name.
+        val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
 
-        // Return the parent folder string.
-        return parentFolder
+        // Return a cursor with all the bookmarks in the specified folder ordered by display order.  The cursor cannot be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName ORDER BY $DISPLAY_ORDER ASC", null)
     }
 
-    // Get a cursor of all the folders.
-    val allFolders: Cursor
-        get() {
-            // Get a readable database handle.
-            val bookmarksDatabase = this.readableDatabase
-
-            // Return the cursor with the all the folders.  The cursor cannot be closed because it is used in the parent activity.
-            return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 ORDER BY $BOOKMARK_NAME ASC", null)
-        }
-
-    // Get a cursor for all bookmarks and folders.
-    val allBookmarks: Cursor
-        get() {
-            // Get a readable database handle.
-            val bookmarksDatabase = this.readableDatabase
-
-            // Return a cursor with the entire contents of the bookmarks table.  The cursor cannot be closed because it is used in the parent activity.
-            return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE", null)
-        }
-
-    // Get a cursor for all bookmarks and folders ordered by display order.
-    val allBookmarksByDisplayOrder: Cursor
-        get() {
-            // Get a readable database handle.
-            val bookmarksDatabase = this.readableDatabase
-
-            // Return a cursor with the entire contents of the bookmarks table ordered by the display order.  The cursor cannot be closed because it is used in the parent activity.
-            return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE ORDER BY $DISPLAY_ORDER ASC", null)
-        }
-
-    // Get a cursor for all bookmarks and folders except those with the specified IDs.
-    fun getAllBookmarksExcept(exceptIdLongArray: LongArray): Cursor {
+    // Get a cursor for bookmarks and folders in the specified folder by display order except those with the specified IDs.
+    fun getBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray, folderName: String): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
@@ -308,12 +277,17 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
             idsNotToGetStringBuilder.append(databaseIdLong)
         }
 
-        // Return a cursor with all the bookmarks except those specified.  The cursor cannot be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder)", null)
+        // SQL escape the folder name.
+        val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
+
+        // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified ordered by display order.
+        // The cursor cannot be closed because it will be used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC",
+            null)
     }
 
-    // Get a cursor for all bookmarks and folders by display order except those with the specified IDs.
-    fun getAllBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray): Cursor {
+    // Get a cursor for bookmarks and folders in the specified folder except those with the specified IDs.
+    fun getBookmarksExcept(exceptIdLongArray: LongArray, folderName: String): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
@@ -332,100 +306,152 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
             idsNotToGetStringBuilder.append(databaseIdLong)
         }
 
-        // Return a cursor with all the bookmarks except those specified ordered by display order.  The cursor cannot be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC", null)
+        // SQL escape the folder name.
+        val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
+
+        // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified.  The cursor cannot be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder)", null)
     }
 
-    // Get a cursor for bookmarks and folders in the specified folder.
-    fun getBookmarks(folderName: String): Cursor {
+    // Get a cursor for the specified folder name.
+    fun getFolder(folderName: String): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
         // SQL escape the folder name.
         val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
 
-        // Return a cursor with all the bookmarks in a specified folder.  The cursor cannot be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null)
+        // Return the cursor for the specified folder.  The cursor can't be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null)
     }
 
-    // Get a cursor for bookmarks and folders in the specified folder ordered by display order.
-    fun getBookmarksByDisplayOrder(folderName: String): Cursor {
-        // Get a readable database handle.
-        val bookmarksDatabase = this.readableDatabase
+    fun getFolderBookmarks(folderDatabaseId: Int): Cursor {
+        // Get the folder name.
+        val folderName = getFolderName(folderDatabaseId)
 
         // SQL escape the folder name.
         val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
 
-        // Return a cursor with all the bookmarks in the specified folder ordered by display order.  The cursor cannot be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName ORDER BY $DISPLAY_ORDER ASC", null)
+        // Get a readable database handle.
+        val bookmarksDatabase = this.readableDatabase
+
+        // Return a cursor with all the bookmarks in the folder.  The cursor cannot be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $IS_FOLDER = 0 ORDER BY $DISPLAY_ORDER ASC", null)
     }
 
-    // Get a cursor with just database ID of bookmarks and folders in the specified folder.  This is useful for deleting folders with bookmarks that have favorite icons too large to fit in a cursor.
-    fun getBookmarkIds(folderName: String): Cursor {
+    // Get the database ID for the specified folder name.
+    fun getFolderDatabaseId(folderName: String): Int {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
         // SQL escape the folder name.
         val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
 
-        // Return a cursor with all the database IDs.  The cursor cannot be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT $ID FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null)
+        // Get the cursor for the folder with the specified name.
+        val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null)
+
+        // Move to the first record.
+        folderCursor.moveToFirst()
+
+        // Get the database ID.
+        val databaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(ID))
+
+        // Close the cursor and the database handle.
+        folderCursor.close()
+        bookmarksDatabase.close()
+
+        // Return the database ID.
+        return databaseId
     }
 
-    // Get a cursor for bookmarks and folders in the specified folder except those with the specified IDs.
-    fun getBookmarksExcept(exceptIdLongArray: LongArray, folderName: String): Cursor {
+    // Get the folder name for the specified database ID.
+    fun getFolderName(databaseId: Int): String {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
-        // Prepare a string builder to contain the comma-separated list of IDs not to get.
-        val idsNotToGetStringBuilder = StringBuilder()
+        // Get the cursor for the folder with the specified database ID.
+        val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
 
-        // Extract the array of IDs not to get to the string builder.
-        for (databaseIdLong in exceptIdLongArray) {
-            // Check to see if there is already a number in the builder.
-            if (idsNotToGetStringBuilder.isNotEmpty()) {
-                // This is not the first number, so place a `,` before the new number.
-                idsNotToGetStringBuilder.append(",")
-            }
+        // Move to the first record.
+        folderCursor.moveToFirst()
 
-            // Add the new number to the builder.
-            idsNotToGetStringBuilder.append(databaseIdLong)
-        }
+        // Get the folder name.
+        val folderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BOOKMARK_NAME))
 
-        // SQL escape the folder name.
-        val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
+        // Close the cursor and the database handle.
+        folderCursor.close()
+        bookmarksDatabase.close()
 
-        // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified.  The cursor cannot be closed because it is used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder)", null)
+        // Return the folder name.
+        return folderName
     }
 
-    // Get a cursor for bookmarks and folders in the specified folder by display order except those with the specified IDs.
-    fun getBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray, folderName: String): Cursor {
+    // Get a cursor of all the folders except those specified.
+    fun getFoldersExcept(exceptFolders: String): Cursor {
         // Get a readable database handle.
         val bookmarksDatabase = this.readableDatabase
 
-        // Prepare a string builder to contain the comma-separated list of IDs not to get.
-        val idsNotToGetStringBuilder = StringBuilder()
+        // Return the cursor of all folders except those specified.  Each individual folder in the list has already been SQL escaped.  The cursor can't be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME NOT IN ($exceptFolders) ORDER BY $BOOKMARK_NAME ASC", null)
+    }
 
-        // Extract the array of IDs not to get to the string builder.
-        for (databaseIdLong in exceptIdLongArray) {
-            // Check to see if there is already a number in the builder.
-            if (idsNotToGetStringBuilder.isNotEmpty()) {
-                // This is not the first number, so place a `,` before the new number.
-                idsNotToGetStringBuilder.append(",")
-            }
+    // Get the name of the parent folder.
+    fun getParentFolderName(currentFolder: String): String {
+        // Get a readable database handle.
+        val bookmarksDatabase = this.readableDatabase
 
-            // Add the new number to the builder.
-            idsNotToGetStringBuilder.append(databaseIdLong)
-        }
+        // SQL escape the current folder.
+        val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder)
 
-        // SQL escape the folder name.
-        val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
+        // Get a cursor for the current folder.
+        val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME = $sqlEscapedCurrentFolder", null)
 
-        // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified ordered by display order.
-        // The cursor cannot be closed because it will be used in the parent activity.
-        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC",
-            null)
+        // Move to the first record.
+        bookmarkCursor.moveToFirst()
+
+        // Store the name of the parent folder.
+        val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER))
+
+        // Close the cursor and the database.
+        bookmarkCursor.close()
+        bookmarksDatabase.close()
+
+        // Return the parent folder string.
+        return parentFolder
+    }
+
+    // Get the name of the parent folder.
+    fun getParentFolderName(databaseId: Int): String {
+        // Get a readable database handle.
+        val bookmarksDatabase = this.readableDatabase
+
+        // Get a cursor for the specified database ID.
+        val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
+
+        // Move to the first record.
+        bookmarkCursor.moveToFirst()
+
+        // Store the name of the parent folder.
+        val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER))
+
+        // Close the cursor and the database.
+        bookmarkCursor.close()
+        bookmarksDatabase.close()
+
+        // Return the parent folder string.
+        return parentFolder
+    }
+
+    // Get a cursor with all the subfolders of the specified folder.
+    fun getSubfolders(currentFolder: String): Cursor {
+        // Get a readable database handle.
+        val bookmarksDatabase = this.readableDatabase
+
+        // SQL escape the current folder.
+        val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder)
+
+        // Return the cursor with the subfolders.  The cursor can't be closed because it is used in the parent activity.
+        return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedCurrentFolder AND $IS_FOLDER = 1", null)
     }
 
     // Check if a database ID is a folder.
@@ -450,6 +476,46 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
         return isFolder
     }
 
+    // Move one bookmark or folder to a new folder.
+    fun moveToFolder(databaseId: Int, newFolder: String) {
+        // Get a writable database handle.
+        val bookmarksDatabase = this.writableDatabase
+
+        // SQL escape the new folder name.
+        val sqlEscapedNewFolder = DatabaseUtils.sqlEscapeString(newFolder)
+
+        // Get a cursor for all the bookmarks in the new folder ordered by display order.
+        val newFolderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedNewFolder ORDER BY $DISPLAY_ORDER ASC", null)
+
+        // Set the new display order.
+        val displayOrder: Int = if (newFolderCursor.count > 0) {  // There are already bookmarks in the folder.
+            // Move to the last bookmark.
+            newFolderCursor.moveToLast()
+
+            // Set the display order to be one greater that the last bookmark.
+            newFolderCursor.getInt(newFolderCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) + 1
+        } else {  // There are no bookmarks in the new folder.
+            // Set the display order to be `0`.
+            0
+        }
+
+        // Close the cursor.
+        newFolderCursor.close()
+
+        // Create a content values.
+        val bookmarkContentValues = ContentValues()
+
+        // Store the new values.
+        bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
+        bookmarkContentValues.put(PARENT_FOLDER, newFolder)
+
+        // Update the database.
+        bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
+
+        // Close the database handle.
+        bookmarksDatabase.close()
+    }
+
     // Update the bookmark name and URL.
     fun updateBookmark(databaseId: Int, bookmarkName: String, bookmarkUrl: String) {
         // Initialize a content values.
@@ -532,6 +598,24 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
         bookmarksDatabase.close()
     }
 
+    // Update the display order for one bookmark or folder.
+    fun updateDisplayOrder(databaseId: Int, displayOrder: Int) {
+        // Get a writable database handle.
+        val bookmarksDatabase = this.writableDatabase
+
+        // Create a content values.
+        val bookmarkContentValues = ContentValues()
+
+        // Store the new display order.
+        bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
+
+        // Update the database.
+        bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
+
+        // Close the database handle.
+        bookmarksDatabase.close()
+    }
+
     // Update the folder name.
     fun updateFolder(databaseId: Int, oldFolderName: String, newFolderName: String) {
         // Get a writable database handle.
@@ -675,74 +759,4 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK
         // Close the database handle.
         bookmarksDatabase.close()
     }
-
-    // Update the display order for one bookmark or folder.
-    fun updateDisplayOrder(databaseId: Int, displayOrder: Int) {
-        // Get a writable database handle.
-        val bookmarksDatabase = this.writableDatabase
-
-        // Create a content values.
-        val bookmarkContentValues = ContentValues()
-
-        // Store the new display order.
-        bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
-
-        // Update the database.
-        bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
-
-        // Close the database handle.
-        bookmarksDatabase.close()
-    }
-
-    // Move one bookmark or folder to a new folder.
-    fun moveToFolder(databaseId: Int, newFolder: String) {
-        // Get a writable database handle.
-        val bookmarksDatabase = this.writableDatabase
-
-        // SQL escape the new folder name.
-        val sqlEscapedNewFolder = DatabaseUtils.sqlEscapeString(newFolder)
-
-        // Get a cursor for all the bookmarks in the new folder ordered by display order.
-        val newFolderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedNewFolder ORDER BY $DISPLAY_ORDER ASC", null)
-
-        // Set the new display order.
-        val displayOrder: Int = if (newFolderCursor.count > 0) {  // There are already bookmarks in the folder.
-            // Move to the last bookmark.
-            newFolderCursor.moveToLast()
-
-            // Set the display order to be one greater that the last bookmark.
-            newFolderCursor.getInt(newFolderCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) + 1
-        } else {  // There are no bookmarks in the new folder.
-            // Set the display order to be `0`.
-            0
-        }
-
-        // Close the cursor.
-        newFolderCursor.close()
-
-        // Create a content values.
-        val bookmarkContentValues = ContentValues()
-
-        // Store the new values.
-        bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
-        bookmarkContentValues.put(PARENT_FOLDER, newFolder)
-
-        // Update the database.
-        bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
-
-        // Close the database handle.
-        bookmarksDatabase.close()
-    }
-
-    // Delete one bookmark.
-    fun deleteBookmark(databaseId: Int) {
-        // Get a writable database handle.
-        val bookmarksDatabase = this.writableDatabase
-
-        // Deletes the row with the given database ID.
-        bookmarksDatabase.delete(BOOKMARKS_TABLE, "$ID = $databaseId", null)
-
-        // Close the database handle.
-        bookmarksDatabase.close()
-    }
-}
\ No newline at end of file
+}