2 * Copyright 2023 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
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.
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.
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/>.
20 // Application headers.
21 #include "BookmarksDatabase.h"
23 // Define the private static schema constants.
24 const int BookmarksDatabase::SCHEMA_VERSION = 0;
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";
38 // Construct the class.
39 BookmarksDatabase::BookmarksDatabase() {}
41 void BookmarksDatabase::addDatabase()
43 // Add the bookmarks database.
44 QSqlDatabase bookmarksDatabase = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), CONNECTION_NAME);
46 // Set the database name.
47 bookmarksDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/bookmarks.db");
50 if (bookmarksDatabase.open()) // Opening the database succeeded.
52 // Check to see if the bookmarks table already exists.
53 if (bookmarksDatabase.tables().contains(BOOKMARKS_TABLE)) // The bookmarks table already exists.
55 // Query the database schema version.
56 QSqlQuery schemaVersionQuery = bookmarksDatabase.exec(QStringLiteral("PRAGMA user_version"));
58 // Move to the first record.
59 schemaVersionQuery.first();
61 // Get the current schema version.
62 int currentSchemaVersion = schemaVersionQuery.value(0).toInt();
64 // Check to see if the schema has been updated.
65 if (currentSchemaVersion < SCHEMA_VERSION)
67 // Run the schema update code.
69 // Update the schema version.
70 bookmarksDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
73 else // The bookmarks table does not exist.
75 // Instantiate a create table query.
76 QSqlQuery createTableQuery(bookmarksDatabase);
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)");
90 if (!createTableQuery.exec())
93 qDebug().noquote().nospace() << "Error creating table: " << bookmarksDatabase.lastError();
96 // Set the schema version.
97 bookmarksDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION));
100 else // Opening the database failed.
102 // Write the last database error message to the debug output.
103 qDebug().noquote().nospace() << "Error opening database: " << bookmarksDatabase.lastError();
107 void BookmarksDatabase::addBookmark(const QString &bookmarkName, const QString &bookmarkUrl, const QIcon &favoriteIcon)
109 // Get a handle for the bookmarks database.
110 QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
112 // Get a favorite icon pixmap.
113 QPixmap favoriteIconPixmap = favoriteIcon.pixmap(32, 32);
115 // Create a favorite icon byte array.
116 QByteArray favoriteIconByteArray;
118 // Create a favorite icon buffer.
119 QBuffer favoriteIconBuffer(&favoriteIconByteArray);
122 favoriteIconBuffer.open(QIODevice::WriteOnly);
124 // Convert the favorite icon pixmap into a byte array in PNG format.
125 favoriteIconPixmap.save(&favoriteIconBuffer, "PNG");
128 favoriteIconBuffer.close();
130 // Convert the favorite icon byte array to a base 64 string.
131 QString favoriteIconBase64String = favoriteIconByteArray.toBase64();
133 // Instantiate an add bookmark query.
134 QSqlQuery addBookmarkQuery(bookmarksDatabase);
136 // Prepare the add bookmark query.
137 addBookmarkQuery.prepare("INSERT INTO " + BOOKMARKS_TABLE + " (" +
138 BOOKMARK_NAME + ", " +
139 BOOKMARK_URL + ", " +
141 "VALUES (:bookmark_name, :bookmark_url, :favorite_icon)"
145 addBookmarkQuery.bindValue(":bookmark_name", bookmarkName);
146 addBookmarkQuery.bindValue(":bookmark_url", bookmarkUrl);
147 addBookmarkQuery.bindValue(":favorite_icon", favoriteIconBase64String);
149 // Execute the query.
150 addBookmarkQuery.exec();
153 std::list<BookmarkStruct>* BookmarksDatabase::getBookmarks()
155 // Get a handle for the bookmarks database.
156 QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
158 // Instantiate a bookmarks query.
159 QSqlQuery bookmarksQuery(bookmarksDatabase);
161 // Set the query to be forward only, which is more performant.
162 bookmarksQuery.setForwardOnly(true);
164 // Prepare the bookmarks query.
165 bookmarksQuery.prepare("SELECT * FROM " + BOOKMARKS_TABLE);
167 // Execute the query.
168 bookmarksQuery.exec();
170 // Create a bookmark list.
171 std::list<BookmarkStruct> *bookmarkListPointer = new std::list<BookmarkStruct>;
173 // Populate the bookmark list.
174 while (bookmarksQuery.next())
176 // Create a bookmark struct.
177 struct BookmarkStruct bookmarkStruct;
179 // Get the favorite icon base 64 bute array.
180 QByteArray favoriteIconByteArray = QByteArray::fromBase64(bookmarksQuery.value(FAVORITE_ICON).toByteArray());
182 // Create a favorite icon pixmap.
183 QPixmap favoriteIconPixmap;
185 // Load the pixmap from byte array.
186 favoriteIconPixmap.loadFromData(favoriteIconByteArray);
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);
194 // Add the bookmark to the list.
195 bookmarkListPointer->push_back(bookmarkStruct);
198 // Return the bookmark list.
199 return bookmarkListPointer;
202 void BookmarksDatabase::updateBookmarkName(const int bookmarkId, const QString &bookmarkName)
204 // Get a handle for the bookmarks database.
205 QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
207 // Instantiate an update bookmark name query.
208 QSqlQuery updateBookmarkNameQuery(bookmarksDatabase);
210 // Prepare the update bookmark name query.
211 updateBookmarkNameQuery.prepare("UPDATE " + BOOKMARKS_TABLE +
212 " SET " + BOOKMARK_NAME + " = :bookmark_name " +
213 "WHERE " + ID + " = :id");
216 updateBookmarkNameQuery.bindValue(":bookmark_name", bookmarkName);
217 updateBookmarkNameQuery.bindValue(":id", bookmarkId);
219 // Execute the query.
220 updateBookmarkNameQuery.exec();
223 void BookmarksDatabase::updateBookmarkUrl(const int bookmarkId, const QString &bookmarkUrl)
225 // Get a handle for the bookmarks database.
226 QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
228 // Instantiate an update bookmark URL query.
229 QSqlQuery updateBookmarkUrlQuery(bookmarksDatabase);
231 // Prepare the update bookmark URL query.
232 updateBookmarkUrlQuery.prepare("UPDATE " + BOOKMARKS_TABLE +
233 " SET " + BOOKMARK_URL + " = :bookmark_url " +
234 "WHERE " + ID + " = :id");
237 updateBookmarkUrlQuery.bindValue(":bookmark_url", bookmarkUrl);
238 updateBookmarkUrlQuery.bindValue(":id", bookmarkId);
240 // Execute the query.
241 updateBookmarkUrlQuery.exec();