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 "BookmarksDialog.h"
22 #include "ui_BookmarksDialog.h"
23 #include "databases/BookmarksDatabase.h"
24 #include "dialogs/AddBookmarkDialog.h"
25 #include "dialogs/EditBookmarkDialog.h"
27 // KDE Frameworks headers.
28 #include <KLocalizedString>
30 // Qt toolkit headers.
32 #include <QStandardItemModel>
34 // Construct the class.
35 BookmarksDialog::BookmarksDialog(QIcon currentWebsiteFavorieIcon) : QDialog(nullptr), websiteFavoriteIcon(currentWebsiteFavorieIcon)
37 // Set the dialog window title.
38 setWindowTitle(i18nc("The bookmarks dialog window title", "Bookmarks"));
40 // Set the window modality.
41 setWindowModality(Qt::WindowModality::ApplicationModal);
43 // Instantiate the bookmarks settings dialog UI.
44 Ui::BookmarksDialog bookmarksDialogUi;
47 bookmarksDialogUi.setupUi(this);
49 // Get a handle for the draggable tree view.
50 draggableTreeViewPointer = bookmarksDialogUi.draggableTreeView;
52 // Initialize the tree model.
53 treeModelPointer = new QStandardItemModel();
55 // Auto resize the headers.
56 draggableTreeViewPointer->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
58 // Indicate that all the rows are the same height, which improves performance.
59 draggableTreeViewPointer->setUniformRowHeights(true);
61 // Set the selection mode to allow multiple rows to be selected at once.
62 draggableTreeViewPointer->setSelectionMode(QAbstractItemView::ExtendedSelection);
64 // Allow dragging of bookmarks to reorder.
65 draggableTreeViewPointer->setDragDropMode(QAbstractItemView::InternalMove);
67 // Set the tree model.
68 draggableTreeViewPointer->setModel(treeModelPointer);
70 // Get a handle for the tree selection model.
71 treeSelectionModelPointer = draggableTreeViewPointer->selectionModel();
73 // Listen for selection changes.
74 connect(treeSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi()));
76 // Repopulate the bookmarks when they are moved.
77 connect(draggableTreeViewPointer, SIGNAL(bookmarksMoved()), this, SLOT(refreshBookmarks()));
79 // Get handles for the buttons.
80 QPushButton *addBookmarkButtonPointer = bookmarksDialogUi.addBookmarkButton;
81 editButtonPointer = bookmarksDialogUi.editButton;
82 deleteItemsButtonPointer = bookmarksDialogUi.deleteItemsButton;
83 QDialogButtonBox *dialogButtonBoxPointer = bookmarksDialogUi.dialogButtonBox;
84 QPushButton *closeButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Close);
86 // Connect the buttons.
87 connect(addBookmarkButtonPointer, SIGNAL(clicked()), this, SLOT(showAddBookmarkDialog()));
88 connect(editButtonPointer, SIGNAL(clicked()), this, SLOT(showEditDialog()));
89 connect(deleteItemsButtonPointer, SIGNAL(clicked()), this, SLOT(deleteItems()));
90 connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
92 // Set the close button to be the default.
93 closeButtonPointer->setDefault(true);
95 // Monitor editing of data in the tree model.
96 connect(treeModelPointer, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateBookmarkFromTree(QStandardItem*)));
98 // Populate the bookmarks.
102 void BookmarksDialog::deleteItems() const
104 // Get the list of selected model indexes.
105 QList<QModelIndex> selectedModelIndexList = treeSelectionModelPointer->selectedRows(DATABASE_ID_COLUMN);
107 // Delete each of the bookmarks.
108 for (const QModelIndex &modelIndex : selectedModelIndexList)
110 // Delete the bookmark.
111 BookmarksDatabase::deleteBookmark(modelIndex.data().toInt());
114 // Repopulate the bookmarks in this dialog
117 // Emit the bookmark updated signal to redraw the bookmarks in the menu and toolbar.
118 emit bookmarkUpdated();
121 void BookmarksDialog::populateBookmarks() const
123 // Clear the current contents of the tree model.
124 treeModelPointer->clear();
126 // Set the column count.
127 treeModelPointer->setColumnCount(4);
129 // Set the tree header data. The last column is the database ID, which is not displayed.
130 treeModelPointer->setHeaderData(BOOKMARK_NAME_COLUMN, Qt::Horizontal, i18nc("The bookmark Name header.", "Name"));
131 treeModelPointer->setHeaderData(BOOKMARK_URL_COLUMN, Qt::Horizontal, i18nc("The bookmark URL header.", "URL"));
133 // Hide the backend columns.
134 draggableTreeViewPointer->setColumnHidden(DATABASE_ID_COLUMN, true);
135 draggableTreeViewPointer->setColumnHidden(DISPLAY_ORDER, true);
137 // Get the list of bookmarks.
138 std::list<BookmarkStruct> *bookmarksListPointer = BookmarksDatabase::getBookmarks();
140 // Populate the bookmarks tree view.
141 for (const BookmarkStruct &bookmarkStruct : *bookmarksListPointer)
143 // Create a list for the bookmark items.
144 QList<QStandardItem*> bookmarkItemList;
146 // Create the bookmark items.
147 QStandardItem *nameItemPointer = new QStandardItem(bookmarkStruct.favoriteIcon, bookmarkStruct.bookmarkName);
148 QStandardItem *urlItemPointer = new QStandardItem(bookmarkStruct.bookmarkUrl);
149 QStandardItem *idItemPointer = new QStandardItem(QString::number(bookmarkStruct.id));
150 QStandardItem *displayOrderPointer = new QStandardItem(QString::number(bookmarkStruct.displayOrder));
152 nameItemPointer->setDragEnabled(true);
153 nameItemPointer->setDropEnabled(true);
155 // Disable dragging the URL.
156 urlItemPointer->setDragEnabled(false);
158 // Disable dropping on the URL. For some reason this doesn't work.
159 urlItemPointer->setDropEnabled(false);
161 // Disable selecting the URL.
162 urlItemPointer->setSelectable(false);
164 // Populate the bookmark item list.
165 bookmarkItemList.append(nameItemPointer);
166 bookmarkItemList.append(urlItemPointer);
167 bookmarkItemList.append(idItemPointer);
168 bookmarkItemList.append(displayOrderPointer);
170 // Add the bookmark to the tree.
171 treeModelPointer->appendRow(bookmarkItemList);
178 void BookmarksDialog::refreshBookmarks() const
180 // Repopulate the bookmarks in this dialog
183 // Emit the bookmark updated signal to redraw the bookmarks in the menu and toolbar.
184 emit bookmarkUpdated();
187 void BookmarksDialog::showAddBookmarkDialog() const
189 // Instantiate an add bookmark dialog.
190 AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(QLatin1String(""), QLatin1String(""), websiteFavoriteIcon);
192 // Update the displayed bookmarks when a new one is added.
193 connect(addBookmarkDialogPointer, SIGNAL(bookmarkAdded()), this, SLOT(refreshBookmarks()));
196 addBookmarkDialogPointer->show();
199 void BookmarksDialog::showEditDialog()
201 // Get the current model index.
202 QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
204 // Instantiate an edit bookmark dialog.
205 QDialog *editBookmarkDialogPointer = new EditBookmarkDialog(currentIndex.siblingAtColumn(DATABASE_ID_COLUMN).data().toInt(), websiteFavoriteIcon);
208 editBookmarkDialogPointer->show();
210 // Process bookmark events.
211 connect(editBookmarkDialogPointer, SIGNAL(bookmarkSaved()), this, SLOT(refreshBookmarks()));
214 void BookmarksDialog::updateBookmarkFromTree(QStandardItem *modifiedStandardItem)
216 // Get the model index of the modified item.
217 QModelIndex modifiedItemModelIndex = modifiedStandardItem->index();
219 // Get the model index of the database ID.
220 QModelIndex databaseIdModelIndex = modifiedItemModelIndex.siblingAtColumn(DATABASE_ID_COLUMN);
222 // Get the database ID.
223 int databaseId = databaseIdModelIndex.data().toInt();
225 // Check to see if the bookmark name or the URL was edited.
226 if (modifiedStandardItem->column() == BOOKMARK_NAME_COLUMN) // The bookmark name was edited.
228 // Update the bookmark name.
229 BookmarksDatabase::updateBookmarkName(databaseId, modifiedStandardItem->text());
231 else // The bookmark URL was edited.
233 // Update the bookmark URL.
234 BookmarksDatabase::updateBookmarkUrl(databaseId, modifiedStandardItem->text());
237 // Emit the bookmark updated signal.
238 emit bookmarkUpdated();
241 void BookmarksDialog::updateUi() const
243 // Set the status of the buttons.
244 if (treeSelectionModelPointer->hasSelection()) // A bookmark or folder is selected.
246 // Enabled the buttons.
247 editButtonPointer->setEnabled(true);
248 deleteItemsButtonPointer->setEnabled(true);
250 // Update the delete items button text.
251 deleteItemsButtonPointer->setText(i18ncp("Delete items button populated text.", "Delete %1 item", "Delete %1 items", treeSelectionModelPointer->selectedRows().count()));
253 else // Nothing is selected.
255 // Disable the buttons.
256 editButtonPointer->setEnabled(false);
257 deleteItemsButtonPointer->setEnabled(false);
259 // Update the delete items button text.
260 deleteItemsButtonPointer->setText(i18nc("Delete items button default text", "Delete items"));