]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/databases/BookmarksDatabase.cpp
Partial bookmark implementation. https://redmine.stoutner.com/issues/968
[PrivacyBrowserPC.git] / src / databases / BookmarksDatabase.cpp
1 /*
2  * Copyright 2023 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
5  *
6  * Privacy Browser PC is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser PC is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 // Application headers.
21 #include "BookmarksDatabase.h"
22
23 // Define the private static schema constants.
24 const int BookmarksDatabase::SCHEMA_VERSION = 0;
25
26 // Define the public static constants.
27 const QString BookmarksDatabase::CONNECTION_NAME = "bookmarks_database";
28 const QString BookmarksDatabase::BOOKMARK_NAME = "bookmark_name";
29 const QString BookmarksDatabase::BOOKMARKS_TABLE = "bookmarks";
30 const QString BookmarksDatabase::BOOKMARK_URL = "bookmark_url";
31 const QString BookmarksDatabase::DISPLAY_ORDER = "display_order";
32 const QString BookmarksDatabase::FAVORITE_ICON = "favorite_icon";
33 const QString BookmarksDatabase::FOLDER_ID = "folder_id";
34 const QString BookmarksDatabase::ID = "_id";
35 const QString BookmarksDatabase::IS_FOLDER = "is_folder";
36 const QString BookmarksDatabase::PARENT_FOLDER_ID = "parent_folder_id";
37
38 // Construct the class.
39 BookmarksDatabase::BookmarksDatabase() {}
40
41 void BookmarksDatabase::addDatabase()
42 {
43     // Add the bookmarks database.
44     QSqlDatabase bookmarksDatabase = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), CONNECTION_NAME);
45
46     // Set the database name.
47     bookmarksDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/bookmarks.db");
48
49     // Open the database.
50     if (bookmarksDatabase.open())  // Opening the database succeeded.
51     {
52         // Check to see if the bookmarks table already exists.
53         if (bookmarksDatabase.tables().contains(BOOKMARKS_TABLE))  // The bookmarks table already exists.
54         {
55             // Query the database schema version.
56             QSqlQuery schemaVersionQuery = bookmarksDatabase.exec(QStringLiteral("PRAGMA user_version"));
57
58             // Move to the first record.
59             schemaVersionQuery.first();
60
61             // Get the current schema version.
62             int currentSchemaVersion = schemaVersionQuery.value(0).toInt();
63
64             // Check to see if the schema has been updated.
65             if (currentSchemaVersion < SCHEMA_VERSION)
66             {
67                 // Run the schema update code.
68
69                 // Update the schema version.
70                 bookmarksDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
71             }
72         }
73         else  // The bookmarks table does not exist.
74         {
75             // Instantiate a create table query.
76             QSqlQuery createTableQuery(bookmarksDatabase);
77
78             // Populate the create table query.
79             createTableQuery.prepare("CREATE TABLE " + BOOKMARKS_TABLE + "(" +
80                                       ID + " INTEGER PRIMARY KEY, " +
81                                       BOOKMARK_NAME + " TEXT, " +
82                                       BOOKMARK_URL + " TEXT, " +
83                                       PARENT_FOLDER_ID + " INTEGER DEFAULT 0, " +
84                                       DISPLAY_ORDER + " INTEGER DEFAULT 0, " +
85                                       IS_FOLDER + " BOOLEAN DEFAULT FALSE, " +
86                                       FOLDER_ID + " INTEGER DEFAULT 0, " +
87                                       FAVORITE_ICON + " BLOB)");
88
89             // Execute the query.
90             if (!createTableQuery.exec())
91             {
92                 // Log any errors.
93                 qDebug().noquote().nospace() << "Error creating table:  " << bookmarksDatabase.lastError();
94             }
95
96             // Set the schema version.
97             bookmarksDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
98         }
99     }
100     else  // Opening the database failed.
101     {
102         // Write the last database error message to the debug output.
103         qDebug().noquote().nospace() << "Error opening database:  " << bookmarksDatabase.lastError();
104     }
105 };
106
107 void BookmarksDatabase::addBookmark(const QString &bookmarkName, const QString &bookmarkUrl, const QIcon &favoriteIcon)
108 {
109     // Get a handle for the bookmarks database.
110     QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
111
112     // Get a favorite icon pixmap.
113     QPixmap favoriteIconPixmap = favoriteIcon.pixmap(32, 32);
114
115     // Create a favorite icon byte array.
116     QByteArray favoriteIconByteArray;
117
118     // Create a favorite icon buffer.
119     QBuffer favoriteIconBuffer(&favoriteIconByteArray);
120
121     // Open the buffer.
122     favoriteIconBuffer.open(QIODevice::WriteOnly);
123
124     // Convert the favorite icon pixmap into a byte array in PNG format.
125     favoriteIconPixmap.save(&favoriteIconBuffer, "PNG");
126
127     // Close the buffer.
128     favoriteIconBuffer.close();
129
130     // Convert the favorite icon byte array to a base 64 string.
131     QString favoriteIconBase64String = favoriteIconByteArray.toBase64();
132
133     // Instantiate an add bookmark query.
134     QSqlQuery addBookmarkQuery(bookmarksDatabase);
135
136     // Prepare the add bookmark query.
137     addBookmarkQuery.prepare("INSERT INTO " + BOOKMARKS_TABLE + " (" +
138                               BOOKMARK_NAME + ", " +
139                               BOOKMARK_URL + ", " +
140                               FAVORITE_ICON + ") "
141                               "VALUES (:bookmark_name, :bookmark_url, :favorite_icon)"
142     );
143
144     // Bind the values.
145     addBookmarkQuery.bindValue(":bookmark_name", bookmarkName);
146     addBookmarkQuery.bindValue(":bookmark_url", bookmarkUrl);
147     addBookmarkQuery.bindValue(":favorite_icon", favoriteIconBase64String);
148
149     // Execute the query.
150     addBookmarkQuery.exec();
151 }
152
153 std::list<BookmarkStruct>* BookmarksDatabase::getBookmarks()
154 {
155     // Get a handle for the bookmarks database.
156     QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
157
158     // Instantiate a bookmarks query.
159     QSqlQuery bookmarksQuery(bookmarksDatabase);
160
161     // Set the query to be forward only, which is more performant.
162     bookmarksQuery.setForwardOnly(true);
163
164     // Prepare the bookmarks query.
165     bookmarksQuery.prepare("SELECT * FROM " + BOOKMARKS_TABLE);
166
167     // Execute the query.
168     bookmarksQuery.exec();
169
170     // Create a bookmark list.
171     std::list<BookmarkStruct> *bookmarkListPointer = new std::list<BookmarkStruct>;
172
173     // Populate the bookmark list.
174     while (bookmarksQuery.next())
175     {
176         // Create a bookmark struct.
177         struct BookmarkStruct bookmarkStruct;
178
179         // Get the favorite icon base 64 bute array.
180         QByteArray favoriteIconByteArray = QByteArray::fromBase64(bookmarksQuery.value(FAVORITE_ICON).toByteArray());
181
182         // Create a favorite icon pixmap.
183         QPixmap favoriteIconPixmap;
184
185         // Load the pixmap from byte array.
186         favoriteIconPixmap.loadFromData(favoriteIconByteArray);
187
188         // Populate the bookmark struct.
189         bookmarkStruct.id = bookmarksQuery.value(ID).toInt();
190         bookmarkStruct.bookmarkName = bookmarksQuery.value(BOOKMARK_NAME).toString();
191         bookmarkStruct.bookmarkUrl = bookmarksQuery.value(BOOKMARK_URL).toString();
192         bookmarkStruct.favoriteIcon = QIcon(favoriteIconPixmap);
193
194         // Add the bookmark to the list.
195         bookmarkListPointer->push_back(bookmarkStruct);
196     }
197
198     // Return the bookmark list.
199     return bookmarkListPointer;
200 }
201
202 void BookmarksDatabase::updateBookmarkName(const int bookmarkId, const QString &bookmarkName)
203 {
204     // Get a handle for the bookmarks database.
205     QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
206
207     // Instantiate an update bookmark name query.
208     QSqlQuery updateBookmarkNameQuery(bookmarksDatabase);
209
210     // Prepare the update bookmark name query.
211     updateBookmarkNameQuery.prepare("UPDATE " + BOOKMARKS_TABLE +
212                                     " SET " + BOOKMARK_NAME + " = :bookmark_name " +
213                                     "WHERE " + ID + " = :id");
214
215     // Bind the values.
216     updateBookmarkNameQuery.bindValue(":bookmark_name", bookmarkName);
217     updateBookmarkNameQuery.bindValue(":id", bookmarkId);
218
219     // Execute the query.
220     updateBookmarkNameQuery.exec();
221 }
222
223 void BookmarksDatabase::updateBookmarkUrl(const int bookmarkId, const QString &bookmarkUrl)
224 {
225     // Get a handle for the bookmarks database.
226     QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
227
228     // Instantiate an update bookmark URL query.
229     QSqlQuery updateBookmarkUrlQuery(bookmarksDatabase);
230
231     // Prepare the update bookmark URL query.
232     updateBookmarkUrlQuery.prepare("UPDATE " + BOOKMARKS_TABLE +
233                                    " SET " + BOOKMARK_URL + " = :bookmark_url " +
234                                    "WHERE " + ID + " = :id");
235
236     // Bind the values.
237     updateBookmarkUrlQuery.bindValue(":bookmark_url", bookmarkUrl);
238     updateBookmarkUrlQuery.bindValue(":id", bookmarkId);
239
240     // Execute the query.
241     updateBookmarkUrlQuery.exec();
242 }