]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/commitdiff
Add dragging and dropping of bookmarks.
authorSoren Stoutner <soren@stoutner.com>
Fri, 1 Sep 2023 00:16:13 +0000 (17:16 -0700)
committerSoren Stoutner <soren@stoutner.com>
Fri, 1 Sep 2023 00:16:13 +0000 (17:16 -0700)
19 files changed:
src/CMakeLists.txt
src/databases/BookmarksDatabase.cpp
src/databases/BookmarksDatabase.h
src/dialogs/AddBookmarkDialog.cpp
src/dialogs/AddBookmarkDialog.h
src/dialogs/BookmarksDialog.cpp
src/dialogs/BookmarksDialog.h
src/dialogs/CMakeLists.txt
src/dialogs/EditBookmarkDialog.cpp [new file with mode: 0644]
src/dialogs/EditBookmarkDialog.h [new file with mode: 0644]
src/structs/BookmarkStruct.h
src/uis/AddBookmarkDialog.ui
src/uis/BookmarksDialog.ui
src/uis/EditBookmarkDialog.ui [new file with mode: 0644]
src/widgets/CMakeLists.txt
src/widgets/DraggableTreeView.cpp [new file with mode: 0644]
src/widgets/DraggableTreeView.h [new file with mode: 0644]
src/windows/BrowserWindow.cpp
src/windows/BrowserWindow.h

index f96399a0612a29de893a31325b1e593a30add3fb..3ecd3c8d5a1d6ac65212213b913beec65f8a63d5 100644 (file)
@@ -42,6 +42,7 @@ ki18n_wrap_ui(privacybrowser
     uis/CookiesDialog.ui
     uis/DomainSettingsDialog.ui
     uis/DurableCookiesDialog.ui
+    uis/EditBookmarkDialog.ui
     uis/SaveDialog.ui
     uis/SettingsGeneral.ui
     uis/SettingsPrivacy.ui
index c290682b3113dd652836ad2353460186ac27a882..fdcb0fdaee31af77131b0492045827c8e8f70bea 100644 (file)
@@ -104,31 +104,35 @@ void BookmarksDatabase::addDatabase()
     }
 };
 
-void BookmarksDatabase::addBookmark(const QString &bookmarkName, const QString &bookmarkUrl, const QIcon &favoriteIcon)
+void BookmarksDatabase::addBookmark(const BookmarkStruct *bookmarkStructPointer)
 {
     // Get a handle for the bookmarks database.
     QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
 
-    // Get a favorite icon pixmap.
-    QPixmap favoriteIconPixmap = favoriteIcon.pixmap(32, 32);
+    // Instantiate a count bookmarks query.  TODO:  This needs to be updated to only count the bookmarks in the current folder.
+    QSqlQuery countBookmarksQuery(bookmarksDatabase);
 
-    // Create a favorite icon byte array.
-    QByteArray favoriteIconByteArray;
+    // Set the query to be forward only, which is more performant.
+    countBookmarksQuery.setForwardOnly(true);
 
-    // Create a favorite icon buffer.
-    QBuffer favoriteIconBuffer(&favoriteIconByteArray);
+    // Prepare the count bookmarks query.
+    countBookmarksQuery.prepare("SELECT " + DISPLAY_ORDER + " FROM " + BOOKMARKS_TABLE);
 
-    // Open the buffer.
-    favoriteIconBuffer.open(QIODevice::WriteOnly);
+    // Execute the count bookmarks query.
+    countBookmarksQuery.exec();
 
-    // Convert the favorite icon pixmap into a byte array in PNG format.
-    favoriteIconPixmap.save(&favoriteIconBuffer, "PNG");
+    // Move to the last row.
+    countBookmarksQuery.last();
 
-    // Close the buffer.
-    favoriteIconBuffer.close();
+    // Initialize a bookmarks count variable.
+    int bookmarksCount = 0;
 
-    // Convert the favorite icon byte array to a base 64 string.
-    QString favoriteIconBase64String = favoriteIconByteArray.toBase64();
+    // Check to see if the query is valid (there is at least one bookmark).
+    if (countBookmarksQuery.isValid())
+    {
+        // Get the number of rows (which is zero based) and add one to calculate the number of bookmarks.
+        bookmarksCount = countBookmarksQuery.at() + 1;
+    }
 
     // Instantiate an add bookmark query.
     QSqlQuery addBookmarkQuery(bookmarksDatabase);
@@ -137,19 +141,127 @@ void BookmarksDatabase::addBookmark(const QString &bookmarkName, const QString &
     addBookmarkQuery.prepare("INSERT INTO " + BOOKMARKS_TABLE + " (" +
                               BOOKMARK_NAME + ", " +
                               BOOKMARK_URL + ", " +
-                              FAVORITE_ICON + ") "
-                              "VALUES (:bookmark_name, :bookmark_url, :favorite_icon)"
+                              FAVORITE_ICON + ", " +
+                              DISPLAY_ORDER + ") " +
+                              "VALUES (:bookmark_name, :bookmark_url, :favorite_icon, :display_order)"
     );
 
-    // Bind the values.
-    addBookmarkQuery.bindValue(":bookmark_name", bookmarkName);
-    addBookmarkQuery.bindValue(":bookmark_url", bookmarkUrl);
-    addBookmarkQuery.bindValue(":favorite_icon", favoriteIconBase64String);
+    // Bind the query values.
+    addBookmarkQuery.bindValue(":bookmark_name", bookmarkStructPointer->bookmarkName);
+    addBookmarkQuery.bindValue(":bookmark_url", bookmarkStructPointer->bookmarkUrl);
+    addBookmarkQuery.bindValue(":favorite_icon", getFavoriteIconBase64String(bookmarkStructPointer->favoriteIcon));
+    addBookmarkQuery.bindValue(":display_order", bookmarksCount);
 
-    // Execute the query.
+    // Execute the add bookmark query.
     addBookmarkQuery.exec();
 }
 
+void BookmarksDatabase::deleteBookmark(const int bookmarkId)
+{
+    // Get a handle for the bookmarks database.
+    QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+    // Instantiate a delete bookmark query.
+    QSqlQuery deleteBookmarkQuery(bookmarksDatabase);
+
+    // Prepare the delete bookmark query.
+    deleteBookmarkQuery.prepare("DELETE FROM " + BOOKMARKS_TABLE + " WHERE " + ID + " = :id");
+
+    // Bind the query values.
+    deleteBookmarkQuery.bindValue(":id", bookmarkId);
+
+    // Execute the query.
+    deleteBookmarkQuery.exec();
+
+    // Reset the display order for the other items in the folder.  TODO:  make this folder aware.
+    // TODO:  Perhaps, for performance reasons, this shouldn't run each time a bookmarks is deleted, but batched at the end.
+
+    // Instantiate a bookmarks query.
+    QSqlQuery bookmarksQuery(bookmarksDatabase);
+
+    // Set the query to be forward only, which is more performant.
+    bookmarksQuery.setForwardOnly(true);
+
+    // Prepare the bookmarks query.
+    bookmarksQuery.prepare("SELECT " + ID + ", " + DISPLAY_ORDER + " FROM " + BOOKMARKS_TABLE + " ORDER BY " + DISPLAY_ORDER + " ASC");
+
+    // Execute the query.
+    bookmarksQuery.exec();
+
+    // Create a new display order int.
+    int newDisplayOrder = 0;
+
+    // Update the display order for each bookmark.
+    while (bookmarksQuery.next())
+    {
+        // Check if the new display order is different than the current display order.
+        if (bookmarksQuery.value(DISPLAY_ORDER).toInt() != newDisplayOrder)
+        {
+            // Instantiate an update display order query.
+            QSqlQuery updateDisplayOrderQuery(bookmarksDatabase);
+
+            // Prepare the update display order query.
+            updateDisplayOrderQuery.prepare("UPDATE " + BOOKMARKS_TABLE + " SET " + DISPLAY_ORDER + " = :display_order WHERE " + ID + " = :id");
+
+            // Bind the query values.
+            updateDisplayOrderQuery.bindValue(":display_order", newDisplayOrder);
+            updateDisplayOrderQuery.bindValue(":id", bookmarksQuery.value(ID).toInt());
+
+            // Execute the query.
+            updateDisplayOrderQuery.exec();
+        }
+
+        // Increment the new display order.
+        ++newDisplayOrder;
+    }
+}
+
+BookmarkStruct *BookmarksDatabase::getBookmark(int bookmarkId)
+{
+    // Get a handle for the bookmarks database.
+    QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+    // Instantiate a bookmark query.
+    QSqlQuery bookmarkQuery(bookmarksDatabase);
+
+    // Set the query to be forward only, which is more performant.
+    bookmarkQuery.setForwardOnly(true);
+
+    // Prepare the bookmark query.
+    bookmarkQuery.prepare("SELECT * FROM " + BOOKMARKS_TABLE + " WHERE " + ID + " = :id");
+
+    // Bind the query values.
+    bookmarkQuery.bindValue(":id", bookmarkId);
+
+    // Execute the query.
+    bookmarkQuery.exec();
+
+    // Move to the first entry.
+    bookmarkQuery.first();
+
+    // Create a bookmark struct.
+    struct BookmarkStruct *bookmarkStructPointer = new BookmarkStruct();
+
+    // Get the favorite icon base 64 byte array.
+    QByteArray favoriteIconByteArray = QByteArray::fromBase64(bookmarkQuery.value(FAVORITE_ICON).toByteArray());
+
+    // Create a favorite icon pixmap.
+    QPixmap favoriteIconPixmap;
+
+    // Load the pixmap from byte array.
+    favoriteIconPixmap.loadFromData(favoriteIconByteArray);
+
+    // Populate the bookmark struct.
+    bookmarkStructPointer->id = bookmarkQuery.value(ID).toInt();
+    bookmarkStructPointer->bookmarkName = bookmarkQuery.value(BOOKMARK_NAME).toString();
+    bookmarkStructPointer->bookmarkUrl = bookmarkQuery.value(BOOKMARK_URL).toString();
+    bookmarkStructPointer->displayOrder = bookmarkQuery.value(DISPLAY_ORDER).toInt();
+    bookmarkStructPointer->favoriteIcon = QIcon(favoriteIconPixmap);
+
+    // Return the bookmark struct pointer.
+    return bookmarkStructPointer;
+}
+
 std::list<BookmarkStruct>* BookmarksDatabase::getBookmarks()
 {
     // Get a handle for the bookmarks database.
@@ -162,7 +274,7 @@ std::list<BookmarkStruct>* BookmarksDatabase::getBookmarks()
     bookmarksQuery.setForwardOnly(true);
 
     // Prepare the bookmarks query.
-    bookmarksQuery.prepare("SELECT * FROM " + BOOKMARKS_TABLE);
+    bookmarksQuery.prepare("SELECT * FROM " + BOOKMARKS_TABLE + " ORDER BY " + DISPLAY_ORDER + " ASC");
 
     // Execute the query.
     bookmarksQuery.exec();
@@ -176,7 +288,7 @@ std::list<BookmarkStruct>* BookmarksDatabase::getBookmarks()
         // Create a bookmark struct.
         struct BookmarkStruct bookmarkStruct;
 
-        // Get the favorite icon base 64 bute array.
+        // Get the favorite icon base 64 byte array.
         QByteArray favoriteIconByteArray = QByteArray::fromBase64(bookmarksQuery.value(FAVORITE_ICON).toByteArray());
 
         // Create a favorite icon pixmap.
@@ -189,6 +301,7 @@ std::list<BookmarkStruct>* BookmarksDatabase::getBookmarks()
         bookmarkStruct.id = bookmarksQuery.value(ID).toInt();
         bookmarkStruct.bookmarkName = bookmarksQuery.value(BOOKMARK_NAME).toString();
         bookmarkStruct.bookmarkUrl = bookmarksQuery.value(BOOKMARK_URL).toString();
+        bookmarkStruct.displayOrder = bookmarksQuery.value(DISPLAY_ORDER).toInt();
         bookmarkStruct.favoriteIcon = QIcon(favoriteIconPixmap);
 
         // Add the bookmark to the list.
@@ -199,6 +312,147 @@ std::list<BookmarkStruct>* BookmarksDatabase::getBookmarks()
     return bookmarkListPointer;
 }
 
+QList<BookmarkStruct>* BookmarksDatabase::getBookmarksExcept(QList<int> *exceptDatabaseIdsListPointer)
+{
+    // Get a handle for the bookmarks database.
+    QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+    // Instantiate a bookmarks query.
+    QSqlQuery bookmarksQuery(bookmarksDatabase);
+
+    // Set the query to be forward only, which is more performant.
+    bookmarksQuery.setForwardOnly(true);
+
+    // Create an IDs not to get string.
+    QString idsNotToGetString;
+
+    for (const int databaseId : *exceptDatabaseIdsListPointer)
+    {
+        // Check to see if there the string already has at least one number.
+        if (!idsNotToGetString.isEmpty())
+        {
+            // This is not the first number, so add a `,`.
+            idsNotToGetString.append(QLatin1Char(','));
+        }
+
+        // Append the database ID.
+        idsNotToGetString.append(QString::number(databaseId));
+    }
+
+    // Prepare the bookmarks query.
+    bookmarksQuery.prepare("SELECT * FROM " + BOOKMARKS_TABLE + " WHERE " + ID + " NOT IN (" + idsNotToGetString + ") ORDER BY " + DISPLAY_ORDER + " ASC");
+
+    // Execute the query.
+    bookmarksQuery.exec();
+
+    // Create a bookmark list.
+    QList<BookmarkStruct> *bookmarkListPointer = new QList<BookmarkStruct>;
+
+    // Populate the bookmark list.
+    while (bookmarksQuery.next())
+    {
+        // Create a bookmark struct.
+        struct BookmarkStruct bookmarkStruct;
+
+        // Get the favorite icon base 64 byte array.
+        QByteArray favoriteIconByteArray = QByteArray::fromBase64(bookmarksQuery.value(FAVORITE_ICON).toByteArray());
+
+        // Create a favorite icon pixmap.
+        QPixmap favoriteIconPixmap;
+
+        // Load the pixmap from byte array.
+        favoriteIconPixmap.loadFromData(favoriteIconByteArray);
+
+        // Populate the bookmark struct.
+        bookmarkStruct.id = bookmarksQuery.value(ID).toInt();
+        bookmarkStruct.bookmarkName = bookmarksQuery.value(BOOKMARK_NAME).toString();
+        bookmarkStruct.bookmarkUrl = bookmarksQuery.value(BOOKMARK_URL).toString();
+        bookmarkStruct.displayOrder = bookmarksQuery.value(DISPLAY_ORDER).toInt();
+        bookmarkStruct.favoriteIcon = QIcon(favoriteIconPixmap);
+
+        // Add the bookmark to the list.
+        bookmarkListPointer->push_back(bookmarkStruct);
+    }
+
+    // Return the bookmark list.
+    return bookmarkListPointer;
+}
+
+QString BookmarksDatabase::getFavoriteIconBase64String(const QIcon &favoriteIcon)
+{
+    // Get a favorite icon pixmap.
+    QPixmap favoriteIconPixmap = favoriteIcon.pixmap(32, 32);
+
+    // Create a favorite icon byte array.
+    QByteArray favoriteIconByteArray;
+
+    // Create a favorite icon buffer.
+    QBuffer favoriteIconBuffer(&favoriteIconByteArray);
+
+    // Open the buffer.
+    favoriteIconBuffer.open(QIODevice::WriteOnly);
+
+    // Convert the favorite icon pixmap into a byte array in PNG format.
+    favoriteIconPixmap.save(&favoriteIconBuffer, "PNG");
+
+    // Close the buffer.
+    favoriteIconBuffer.close();
+
+    // Convert the favorite icon byte array to a base 64 string.
+    QString favoriteIconBase64String = favoriteIconByteArray.toBase64();
+
+    // Return the favorite icon base 64 string.
+    return favoriteIconBase64String;
+}
+
+void BookmarksDatabase::updateBookmark(const BookmarkStruct *bookmarkStructPointer)
+{
+    // Get a handle for the bookmarks database.
+    QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+    // Instantiate an update bookmark name.
+    QSqlQuery updateBookmarkQuery(bookmarksDatabase);
+
+    // Prepare the update bookmark query.
+    updateBookmarkQuery.prepare("UPDATE " + BOOKMARKS_TABLE + " SET " +
+                                BOOKMARK_NAME + " = :bookmark_name, " +
+                                BOOKMARK_URL + " = :bookmark_url, " +
+                                DISPLAY_ORDER + " = :display_order, " +
+                                FAVORITE_ICON + "= :favorite_icon " +
+                                "WHERE " + ID + " = :id");
+
+    // Bind the query values.
+    updateBookmarkQuery.bindValue(":bookmark_name", bookmarkStructPointer->bookmarkName);
+    updateBookmarkQuery.bindValue(":bookmark_url", bookmarkStructPointer->bookmarkUrl);
+    updateBookmarkQuery.bindValue(":display_order", bookmarkStructPointer->displayOrder);
+    updateBookmarkQuery.bindValue(":favorite_icon", getFavoriteIconBase64String(bookmarkStructPointer->favoriteIcon));
+    updateBookmarkQuery.bindValue(":id", bookmarkStructPointer->id);
+
+    // Execute the query.
+    updateBookmarkQuery.exec();
+}
+
+void BookmarksDatabase::updateDisplayOrder(const int bookmarkId, const int displayOrder)
+{
+    // Get a handle for the bookmarks database.
+    QSqlDatabase bookmarksDatabase = QSqlDatabase::database(CONNECTION_NAME);
+
+    // Instantiate an update bookmark display order query.
+    QSqlQuery updateBookmarkDisplayOrderQuery(bookmarksDatabase);
+
+    // Prepare the update bookmark display order query.
+    updateBookmarkDisplayOrderQuery.prepare("UPDATE " + BOOKMARKS_TABLE +
+                                            " SET " + DISPLAY_ORDER + " = :display_order " +
+                                            "WHERE " + ID + " = :id");
+
+    // Bind the query values.
+    updateBookmarkDisplayOrderQuery.bindValue(":display_order", displayOrder);
+    updateBookmarkDisplayOrderQuery.bindValue(":id", bookmarkId);
+
+    // Execute the query.
+    updateBookmarkDisplayOrderQuery.exec();
+}
+
 void BookmarksDatabase::updateBookmarkName(const int bookmarkId, const QString &bookmarkName)
 {
     // Get a handle for the bookmarks database.
@@ -212,7 +466,7 @@ void BookmarksDatabase::updateBookmarkName(const int bookmarkId, const QString &
                                     " SET " + BOOKMARK_NAME + " = :bookmark_name " +
                                     "WHERE " + ID + " = :id");
 
-    // Bind the values.
+    // Bind the query values.
     updateBookmarkNameQuery.bindValue(":bookmark_name", bookmarkName);
     updateBookmarkNameQuery.bindValue(":id", bookmarkId);
 
@@ -233,7 +487,7 @@ void BookmarksDatabase::updateBookmarkUrl(const int bookmarkId, const QString &b
                                    " SET " + BOOKMARK_URL + " = :bookmark_url " +
                                    "WHERE " + ID + " = :id");
 
-    // Bind the values.
+    // Bind the query values.
     updateBookmarkUrlQuery.bindValue(":bookmark_url", bookmarkUrl);
     updateBookmarkUrlQuery.bindValue(":id", bookmarkId);
 
index d0f743a500d271f43496ef5ec8540f41e42fe62a..35f94bd23c7b2193aa81d7c915d0f01a9fadd6e6 100644 (file)
@@ -33,9 +33,14 @@ public:
     BookmarksDatabase();
 
     // The public functions.
-    static void addBookmark(const QString &bookmarkName, const QString &bookmarkUrl, const QIcon &favoriteIcon);
+    static void addBookmark(const BookmarkStruct *bookmarkStructPointer);
     static void addDatabase();
+    static void deleteBookmark(const int bookmarkId);
+    static BookmarkStruct* getBookmark(int bookmarkId);
     static std::list<BookmarkStruct>* getBookmarks();
+    static QList<BookmarkStruct>* getBookmarksExcept(QList<int> *exceptDatabaseIdsListPointer);
+    static void updateBookmark(const BookmarkStruct *bookmarkStructPointer);
+    static void updateDisplayOrder(const int bookmarkId, const int displayOrder);
     static void updateBookmarkName(const int bookmarkId, const QString &bookmarkName);
     static void updateBookmarkUrl(const int bookmarkId, const QString &bookmarkUrl);
 
@@ -51,8 +56,11 @@ public:
     static const QString IS_FOLDER;
     static const QString PARENT_FOLDER_ID;
 
-    private:
+private:
     // The private static constants.
     static const int SCHEMA_VERSION;
+
+    // The private functions.
+    static QString getFavoriteIconBase64String(const QIcon &favoriteIcon);
 };
 #endif
index cc0d132d0c2a41d5b3fbea32a79f5f09be3b8e52..222a69a2fd71c7c1815e0ae765193df7cdee0772 100644 (file)
 #include <KLocalizedString>
 
 // Qt toolkit headers.
+#include <QFileDialog>
 #include <QPushButton>
 
 // Construct the class.
-AddBookmarkDialog::AddBookmarkDialog(const QString &bookmarkName, const QString &bookmarkUrl, const QIcon &favoriteIcon) : QDialog(nullptr), icon(favoriteIcon)
+AddBookmarkDialog::AddBookmarkDialog(const QString &bookmarkName, const QString &bookmarkUrl, const QIcon &favoriteIcon) : QDialog(nullptr)
 {
     // Set the window title.
     setWindowTitle(i18nc("The add bookmark dialog window title.", "Add Bookmark"));
@@ -44,28 +45,21 @@ AddBookmarkDialog::AddBookmarkDialog(const QString &bookmarkName, const QString
     addBookmarkDialogUi.setupUi(this);
 
     // Get handles for the widgets.
-    QGraphicsView *favoriteIconGraphicsViewPointer = addBookmarkDialogUi.favoriteIconGraphicsView;
+    defaultFavoriteIconRadioButtonPointer = addBookmarkDialogUi.defaultFavoriteIconRadioButton;
+    customFavoriteIconRadioButtonPointer = addBookmarkDialogUi.customFavoriteIconRadioButton;
     bookmarkNamePointer = addBookmarkDialogUi.bookmarkNameLineEdit;
     bookmarkUrlPointer = addBookmarkDialogUi.bookmarkUrlLineEdit;
+    QPushButton *browseButtonPointer = addBookmarkDialogUi.browseButton;
     QDialogButtonBox *dialogButtonBoxPointer = addBookmarkDialogUi.dialogButtonBox;
 
-    // Create a graphics scene.
-    QGraphicsScene *favoriteIconGraphicsScenePointer = new QGraphicsScene(this);
-
-    // Set the graphics scene.
-    favoriteIconGraphicsViewPointer->setScene(favoriteIconGraphicsScenePointer);
-
-    // Set the background of the graphics view to be the same as the window
-    favoriteIconGraphicsViewPointer->setBackgroundRole(QPalette::Window);
-
-    // Add the MIME type icon to the scene.
-    favoriteIconGraphicsScenePointer->addPixmap(favoriteIcon.pixmap(32, 32));
+    // Set the default favorite icon.
+    defaultFavoriteIconRadioButtonPointer->setIcon(favoriteIcon);
 
     // Populate the line edits.
     bookmarkNamePointer->setText(bookmarkName);
     bookmarkUrlPointer->setText(bookmarkUrl);
 
-    // Scroll the the beginning of the line edits.
+    // Scroll to the beginning of the line edits.
     bookmarkNamePointer->setCursorPosition(0);
     bookmarkUrlPointer->setCursorPosition(0);
 
@@ -76,16 +70,47 @@ AddBookmarkDialog::AddBookmarkDialog(const QString &bookmarkName, const QString
     addBookmarkButtonPointer->setIcon(QIcon::fromTheme("list-add"));
 
     // Connect the buttons.
+    connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(browse()));
     connect(dialogButtonBoxPointer, SIGNAL(accepted()), this, SLOT(addBookmark()));
     connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
 }
 
 void AddBookmarkDialog::addBookmark()
 {
+    // Get the favorite icon.
+    QIcon favoriteIcon = defaultFavoriteIconRadioButtonPointer->isChecked() ? defaultFavoriteIconRadioButtonPointer->icon() : customFavoriteIconRadioButtonPointer->icon();
+
+    // Create a bookmark struct.
+    BookmarkStruct *bookmarkStructPointer = new BookmarkStruct;
+
+    // Populate the bookmark struct.
+    bookmarkStructPointer->bookmarkName = bookmarkNamePointer->text();
+    bookmarkStructPointer->bookmarkUrl = bookmarkUrlPointer->text();
+    bookmarkStructPointer->favoriteIcon = favoriteIcon;
+
     // Add the bookmark.
-    BookmarksDatabase::addBookmark(bookmarkNamePointer->text(), bookmarkUrlPointer->text(), icon);
+    BookmarksDatabase::addBookmark(bookmarkStructPointer);
+
+    // Update the list of bookmarks in the menu and toolbar.
+    emit bookmarkAdded();
 
     // Close the dialog.
     close();
 }
 
+void AddBookmarkDialog::browse()
+{
+    // Get an image file string from the user.
+    QString imageFileString = QFileDialog::getOpenFileName(this, tr("Favorite Icon Image"), QDir::homePath(),
+                                                           tr("Image Files — *.bmp, *.gif, *.jpg, *.jpeg, *.png, *.svg (*.bmp *.gif *.jpg *.jpeg *.png *.svg);;All Files (*)"));
+
+    // Check to see if an image file string was returned.  This will be empty if the user selected cancel.
+    if (!imageFileString.isEmpty())
+    {
+        // Set the custom favorite icon.
+        customFavoriteIconRadioButtonPointer->setIcon(QIcon(imageFileString));
+
+        // Check the custom favorite icon radio button.
+        customFavoriteIconRadioButtonPointer->setChecked(true);
+    }
+}
index 2cee8b90a0ec2e1d35c99261919093aaa6fd5d8f..c054876690e168a34b8e83095987c64e20dc9217 100644 (file)
@@ -22,8 +22,8 @@
 
 // Qt toolkit headers.
 #include <QDialog>
-#include <QIcon>
 #include <QLineEdit>
+#include <QRadioButton>
 
 class AddBookmarkDialog : public QDialog
 {
@@ -34,16 +34,20 @@ public:
     // The primary constructor.
     explicit AddBookmarkDialog(const QString &bookmarkName, const QString &bookmarkUrl, const QIcon &favoriteIcon);
 
+signals:
+    // The signals.
+    void bookmarkAdded() const;
+
 private Q_SLOTS:
     // The private slots.
     void addBookmark();
+    void browse();
 
 private:
     // The private widgets.
     QLineEdit *bookmarkNamePointer;
     QLineEdit *bookmarkUrlPointer;
-
-    // The private variables.
-    const QIcon icon;
+    QRadioButton *customFavoriteIconRadioButtonPointer;
+    QRadioButton *defaultFavoriteIconRadioButtonPointer;
 };
 #endif
index 509fade9f7796b3e6f240c8ac30a7b958fa1cf4a..4dc66ee873a04b892564b5e35b0f3a901c5551b9 100644 (file)
@@ -21,6 +21,8 @@
 #include "BookmarksDialog.h"
 #include "ui_BookmarksDialog.h"
 #include "databases/BookmarksDatabase.h"
+#include "dialogs/AddBookmarkDialog.h"
+#include "dialogs/EditBookmarkDialog.h"
 
 // KDE Frameworks headers.
 #include <KLocalizedString>
 // Qt toolkit headers.
 #include <QDebug>
 #include <QStandardItemModel>
-#include <QTreeView>
 
 // Construct the class.
-BookmarksDialog::BookmarksDialog() : QDialog(nullptr)
+BookmarksDialog::BookmarksDialog(QIcon currentWebsiteFavorieIcon) : QDialog(nullptr), websiteFavoriteIcon(currentWebsiteFavorieIcon)
 {
     // Set the dialog window title.
     setWindowTitle(i18nc("The bookmarks dialog window title", "Bookmarks"));
@@ -45,62 +46,169 @@ BookmarksDialog::BookmarksDialog() : QDialog(nullptr)
     // Setup the UI.
     bookmarksDialogUi.setupUi(this);
 
-    // Get the list of bookmarks.
-    std::list<BookmarkStruct> *bookmarksListPointer = BookmarksDatabase::getBookmarks();
-
-    // Get a handle for the tree view.
-    QTreeView *treeViewPointer = bookmarksDialogUi.treeView;
+    // Get a handle for the draggable tree view.
+    draggableTreeViewPointer = bookmarksDialogUi.draggableTreeView;
 
     // Initialize the tree model.
-    QStandardItemModel *treeModelPointer = new QStandardItemModel();
+    treeModelPointer = new QStandardItemModel();
+
+    // Auto resize the headers.
+    draggableTreeViewPointer->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+
+    // Indicate that all the rows are the same height, which improves performance.
+    draggableTreeViewPointer->setUniformRowHeights(true);
+
+    // Set the selection mode to allow multiple rows to be selected at once.
+    draggableTreeViewPointer->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+    // Allow dragging of bookmarks to reorder.
+    draggableTreeViewPointer->setDragDropMode(QAbstractItemView::InternalMove);
+
+    // Set the tree model.
+    draggableTreeViewPointer->setModel(treeModelPointer);
+
+    // Get a handle for the tree selection model.
+    treeSelectionModelPointer = draggableTreeViewPointer->selectionModel();
+
+    // Listen for selection changes.
+    connect(treeSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi()));
+
+    // Repopulate the bookmarks when they are moved.
+    connect(draggableTreeViewPointer, SIGNAL(bookmarksMoved()), this, SLOT(refreshBookmarks()));
+
+    // Get handles for the buttons.
+    QPushButton *addBookmarkButtonPointer = bookmarksDialogUi.addBookmarkButton;
+    editButtonPointer = bookmarksDialogUi.editButton;
+    deleteItemsButtonPointer = bookmarksDialogUi.deleteItemsButton;
+    QDialogButtonBox *dialogButtonBoxPointer = bookmarksDialogUi.dialogButtonBox;
+    QPushButton *closeButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Close);
+
+    // Connect the buttons.
+    connect(addBookmarkButtonPointer, SIGNAL(clicked()), this, SLOT(showAddBookmarkDialog()));
+    connect(editButtonPointer, SIGNAL(clicked()), this, SLOT(showEditDialog()));
+    connect(deleteItemsButtonPointer, SIGNAL(clicked()), this, SLOT(deleteItems()));
+    connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
+
+    // Set the close button to be the default.
+    closeButtonPointer->setDefault(true);
+
+    // Monitor editing of data in the tree model.
+    connect(treeModelPointer, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateBookmarkFromTree(QStandardItem*)));
+
+    // Populate the bookmarks.
+    populateBookmarks();
+}
+
+void BookmarksDialog::deleteItems() const
+{
+    // Get the list of selected model indexes.
+    QList<QModelIndex> selectedModelIndexList = treeSelectionModelPointer->selectedRows(DATABASE_ID_COLUMN);
+
+    // Delete each of the bookmarks.
+    for (const QModelIndex &modelIndex : selectedModelIndexList)
+    {
+        // Delete the bookmark.
+        BookmarksDatabase::deleteBookmark(modelIndex.data().toInt());
+    }
+
+    // Repopulate the bookmarks in this dialog
+    populateBookmarks();
+
+    // Emit the bookmark updated signal to redraw the bookmarks in the menu and toolbar.
+    emit bookmarkUpdated();
+}
+
+void BookmarksDialog::populateBookmarks() const
+{
+    // Clear the current contents of the tree model.
+    treeModelPointer->clear();
 
     // Set the column count.
-    treeModelPointer->setColumnCount(3);
+    treeModelPointer->setColumnCount(4);
 
-    // Set the tree header data.  The first column is the database ID, which is not displayed.
-    treeModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The bookmark Name header.", "Name"));
-    treeModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The bookmark URL header.", "URL"));
+    // Set the tree header data.  The last column is the database ID, which is not displayed.
+    treeModelPointer->setHeaderData(BOOKMARK_NAME_COLUMN, Qt::Horizontal, i18nc("The bookmark Name header.", "Name"));
+    treeModelPointer->setHeaderData(BOOKMARK_URL_COLUMN, Qt::Horizontal, i18nc("The bookmark URL header.", "URL"));
+
+    // Hide the backend columns.
+    draggableTreeViewPointer->setColumnHidden(DATABASE_ID_COLUMN, true);
+    draggableTreeViewPointer->setColumnHidden(DISPLAY_ORDER, true);
+
+    // Get the list of bookmarks.
+    std::list<BookmarkStruct> *bookmarksListPointer = BookmarksDatabase::getBookmarks();
 
     // Populate the bookmarks tree view.
-    for (BookmarkStruct bookmarkStruct : *bookmarksListPointer)
+    for (const BookmarkStruct &bookmarkStruct : *bookmarksListPointer)
     {
         // Create a list for the bookmark items.
         QList<QStandardItem*> bookmarkItemList;
 
         // Create the bookmark items.
-        QStandardItem *idItemPointer = new QStandardItem(QString::number(bookmarkStruct.id));
         QStandardItem *nameItemPointer = new QStandardItem(bookmarkStruct.favoriteIcon, bookmarkStruct.bookmarkName);
         QStandardItem *urlItemPointer = new QStandardItem(bookmarkStruct.bookmarkUrl);
+        QStandardItem *idItemPointer = new QStandardItem(QString::number(bookmarkStruct.id));
+        QStandardItem *displayOrderPointer = new QStandardItem(QString::number(bookmarkStruct.displayOrder));
 
-        // Populate the cookie standard item list.
-        bookmarkItemList.append(idItemPointer);
+        nameItemPointer->setDragEnabled(true);
+        nameItemPointer->setDropEnabled(true);
+
+        // Disable dragging the URL.
+        urlItemPointer->setDragEnabled(false);
+
+        // Disable dropping on the URL.  For some reason this doesn't work.
+        urlItemPointer->setDropEnabled(false);
+
+        // Disable selecting the URL.
+        urlItemPointer->setSelectable(false);
+
+        // Populate the bookmark item list.
         bookmarkItemList.append(nameItemPointer);
         bookmarkItemList.append(urlItemPointer);
+        bookmarkItemList.append(idItemPointer);
+        bookmarkItemList.append(displayOrderPointer);
 
-        // Add the cookie to the tree.
+        // Add the bookmark to the tree.
         treeModelPointer->appendRow(bookmarkItemList);
     }
 
-    // Auto resize the headers.
-    treeViewPointer->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+    // Update the UI.
+    updateUi();
+}
 
-    // Indicate that all the rows are the same height, which improves performance.
-    treeViewPointer->setUniformRowHeights(true);
+void BookmarksDialog::refreshBookmarks() const
+{
+    // Repopulate the bookmarks in this dialog
+    populateBookmarks();
 
-    // Set the tree model.
-    treeViewPointer->setModel(treeModelPointer);
+    // Emit the bookmark updated signal to redraw the bookmarks in the menu and toolbar.
+    emit bookmarkUpdated();
+}
 
-    // Hide the database ID column.
-    treeViewPointer->setColumnHidden(0, true);
+void BookmarksDialog::showAddBookmarkDialog() const
+{
+    // Instantiate an add bookmark dialog.
+    AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(QLatin1String(""), QLatin1String(""), websiteFavoriteIcon);
 
-    // Get handles for the buttons.
-    QDialogButtonBox *dialogButtonBoxPointer = bookmarksDialogUi.dialogButtonBox;
+    // Update the displayed bookmarks when a new one is added.
+    connect(addBookmarkDialogPointer, SIGNAL(bookmarkAdded()), this, SLOT(refreshBookmarks()));
 
-    // Connect the buttons.
-    connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
+    // Show the dialog.
+    addBookmarkDialogPointer->show();
+}
 
-    // Monitor editing of data in the tree model.
-    connect(treeModelPointer, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateBookmarkFromTree(QStandardItem*)));
+void BookmarksDialog::showEditDialog()
+{
+    // Get the current model index.
+    QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
+
+    // Instantiate an edit bookmark dialog.
+    QDialog *editBookmarkDialogPointer = new EditBookmarkDialog(currentIndex.siblingAtColumn(DATABASE_ID_COLUMN).data().toInt(), websiteFavoriteIcon);
+
+    // Show the dialog.
+    editBookmarkDialogPointer->show();
+
+    // Process bookmark events.
+    connect(editBookmarkDialogPointer, SIGNAL(bookmarkSaved()), this, SLOT(refreshBookmarks()));
 }
 
 void BookmarksDialog::updateBookmarkFromTree(QStandardItem *modifiedStandardItem)
@@ -109,13 +217,13 @@ void BookmarksDialog::updateBookmarkFromTree(QStandardItem *modifiedStandardItem
     QModelIndex modifiedItemModelIndex = modifiedStandardItem->index();
 
     // Get the model index of the database ID.
-    QModelIndex databaseIdModelIndex = modifiedItemModelIndex.siblingAtColumn(0);
+    QModelIndex databaseIdModelIndex = modifiedItemModelIndex.siblingAtColumn(DATABASE_ID_COLUMN);
 
     // Get the database ID.
     int databaseId = databaseIdModelIndex.data().toInt();
 
     // Check to see if the bookmark name or the URL was edited.
-    if (modifiedStandardItem->column() == 1)  // The bookmark name was edited.
+    if (modifiedStandardItem->column() == BOOKMARK_NAME_COLUMN)  // The bookmark name was edited.
     {
         // Update the bookmark name.
         BookmarksDatabase::updateBookmarkName(databaseId, modifiedStandardItem->text());
@@ -129,3 +237,26 @@ void BookmarksDialog::updateBookmarkFromTree(QStandardItem *modifiedStandardItem
     // Emit the bookmark updated signal.
     emit bookmarkUpdated();
 }
+
+void BookmarksDialog::updateUi() const
+{
+    // Set the status of the buttons.
+    if (treeSelectionModelPointer->hasSelection())  // A bookmark or folder is selected.
+    {
+        // Enabled the buttons.
+        editButtonPointer->setEnabled(true);
+        deleteItemsButtonPointer->setEnabled(true);
+
+        // Update the delete items button text.
+        deleteItemsButtonPointer->setText(i18ncp("Delete items button populated text.", "Delete %1 item", "Delete %1 items", treeSelectionModelPointer->selectedRows().count()));
+    }
+    else  // Nothing is selected.
+    {
+        // Disable the buttons.
+        editButtonPointer->setEnabled(false);
+        deleteItemsButtonPointer->setEnabled(false);
+
+        // Update the delete items button text.
+        deleteItemsButtonPointer->setText(i18nc("Delete items button default text", "Delete items"));
+    }
+}
index 3e2713e4c39ee974944146a6d3ec7d683bbfbaa8..e81d0b41cf008f38ce07e398a67eae0b69c5b2a9 100644 (file)
 
 // Application headers.
 #include "structs/BookmarkStruct.h"
+#include "widgets/DraggableTreeView.h"
 
 // Qt toolkit headers.
 #include <QDialog>
+#include <QItemSelectionModel>
 #include <QStandardItem>
 
 class BookmarksDialog : public QDialog
@@ -34,7 +36,13 @@ class BookmarksDialog : public QDialog
 
 public:
     // The primary constructor.
-    explicit BookmarksDialog();
+    explicit BookmarksDialog(QIcon currentWebsiteFavoriteIcon);
+
+    // The public constants.
+    static const int BOOKMARK_NAME_COLUMN = 0;
+    static const int BOOKMARK_URL_COLUMN = 1;
+    static const int DATABASE_ID_COLUMN = 2;
+    static const int DISPLAY_ORDER = 3;
 
 signals:
     // The signals.
@@ -42,6 +50,23 @@ signals:
 
 private Q_SLOTS:
     // The private slots.
+    void deleteItems() const;
+    void refreshBookmarks() const;
+    void showAddBookmarkDialog() const;
+    void showEditDialog();
     void updateBookmarkFromTree(QStandardItem *modifiedStandardItem);
+    void updateUi() const;
+
+private:
+    // The private functions.
+    void populateBookmarks() const;
+
+    // The private variables.
+    QPushButton *deleteItemsButtonPointer;
+    QPushButton *editButtonPointer;
+    QStandardItemModel *treeModelPointer;
+    QItemSelectionModel *treeSelectionModelPointer;
+    DraggableTreeView *draggableTreeViewPointer;
+    QIcon websiteFavoriteIcon;
 };
 #endif
index b5d7cfd4229f9707451111c3fa40f11bdacc2e42..a1cc4d0646da136c23c283394d83b82ec033decc 100644 (file)
@@ -24,5 +24,6 @@ target_sources(privacybrowser PRIVATE
     CookiesDialog.cpp
     DomainSettingsDialog.cpp
     DurableCookiesDialog.cpp
+    EditBookmarkDialog.cpp
     SaveDialog.cpp
 )
diff --git a/src/dialogs/EditBookmarkDialog.cpp b/src/dialogs/EditBookmarkDialog.cpp
new file mode 100644 (file)
index 0000000..35582f1
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2023 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ *
+ * Privacy Browser PC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser PC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Application headers.
+#include "EditBookmarkDialog.h"
+#include "ui_EditBookmarkDialog.h"
+#include "databases/BookmarksDatabase.h"
+
+// Qt toolkit headers.
+#include <QFileDialog>
+
+// Construct the class.
+EditBookmarkDialog::EditBookmarkDialog(const int bookmarkId, QIcon &currentWebsiteFavoriteIcon) : QDialog(nullptr), bookmarkDatabaseId(bookmarkId)
+{
+    // Set the window title.
+    setWindowTitle(i18nc("The edit bookmark dialog window title.", "Edit Bookmark"));
+
+    // Set the window modality.
+    setWindowModality(Qt::WindowModality::ApplicationModal);
+
+    // Instantiate the bookmarks dialog UI.
+    Ui::EditBookmarkDialog editBookmarkDialogUi;
+
+    // Setup the UI.
+    editBookmarkDialogUi.setupUi(this);
+
+    // Get handles for the widgets.
+    currentFavoriteIconRadioButtonPointer = editBookmarkDialogUi.currentFavoriteIconRadioButton;
+    currentWebsiteFavoritIconRadioButtonPointer = editBookmarkDialogUi.currentWebsiteFavoriteIconRadioButton;
+    customFavoriteIconRadioButtonPointer = editBookmarkDialogUi.customFavoriteIconRadioButton;
+    bookmarkNamePointer = editBookmarkDialogUi.bookmarkNameLineEdit;
+    bookmarkUrlPointer = editBookmarkDialogUi.bookmarkUrlLineEdit;
+    QPushButton *browseButtonPointer = editBookmarkDialogUi.browseButton;
+    QDialogButtonBox *dialogButtonBoxPointer = editBookmarkDialogUi.dialogButtonBox;
+
+    // Get the bookmark struct.
+    bookmarkStructPointer = BookmarksDatabase::getBookmark(bookmarkId);
+
+    // Set the favorite icons.
+    currentFavoriteIconRadioButtonPointer->setIcon(bookmarkStructPointer->favoriteIcon);
+    currentWebsiteFavoritIconRadioButtonPointer->setIcon(currentWebsiteFavoriteIcon);
+
+    // Populate the line edits.
+    bookmarkNamePointer->setText(bookmarkStructPointer->bookmarkName);
+    bookmarkUrlPointer->setText(bookmarkStructPointer->bookmarkUrl);
+
+    // Scroll to the beginning of the line edits.
+    bookmarkNamePointer->setCursorPosition(0);
+    bookmarkUrlPointer->setCursorPosition(0);
+
+    // Connect the buttons.
+    connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(browse()));
+    connect(dialogButtonBoxPointer, SIGNAL(accepted()), this, SLOT(save()));
+    connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+void EditBookmarkDialog::browse()
+{
+    // Get an image file string from the user.
+    QString imageFileString = QFileDialog::getOpenFileName(this, tr("Favorite Icon Image"), QDir::homePath(),
+                                                           tr("Image Files — *.bmp, *.gif, *.jpg, *.jpeg, *.png, *.svg (*.bmp *.gif *.jpg *.jpeg *.png *.svg);;All Files (*)"));
+
+    // Check to see if an image file string was returned.  This will be empty if the user selected cancel.
+    if (!imageFileString.isEmpty())
+    {
+        // Set the custom favorite icon.
+        customFavoriteIconRadioButtonPointer->setIcon(QIcon(imageFileString));
+
+        // Check the custom favorite icon radio button.
+        customFavoriteIconRadioButtonPointer->setChecked(true);
+    }
+}
+
+void EditBookmarkDialog::save()
+{
+    // Create a favorite icon.
+    QIcon favoriteIcon;
+
+    // Get the favorite icon.
+    if (currentFavoriteIconRadioButtonPointer->isChecked())  // The current favorite icon is checked.
+        favoriteIcon = currentFavoriteIconRadioButtonPointer->icon();
+    else if (currentWebsiteFavoritIconRadioButtonPointer->isChecked())  // The current website favorite icon is checked.
+        favoriteIcon = currentWebsiteFavoritIconRadioButtonPointer->icon();
+    else  // The custom favorite icon is checked.
+        favoriteIcon = customFavoriteIconRadioButtonPointer->icon();
+
+    qDebug() << "Favorite icon:  " << favoriteIcon;
+
+    // Create a bookmark struct.
+    BookmarkStruct *bookmarkStructPointer = new BookmarkStruct;
+
+    // Populate the bookmark struct.
+    bookmarkStructPointer->id = bookmarkDatabaseId;
+    bookmarkStructPointer->bookmarkName = bookmarkNamePointer->text();
+    bookmarkStructPointer->bookmarkUrl = bookmarkUrlPointer->text();
+    bookmarkStructPointer->displayOrder = bookmarkStructPointer->displayOrder;
+    bookmarkStructPointer->favoriteIcon = favoriteIcon;
+
+    // Update the bookmark.
+    BookmarksDatabase::updateBookmark(bookmarkStructPointer);
+
+    // Emit the bookmark saved signal.
+    emit bookmarkSaved();
+
+    // Close the dialog.
+    close();
+}
diff --git a/src/dialogs/EditBookmarkDialog.h b/src/dialogs/EditBookmarkDialog.h
new file mode 100644 (file)
index 0000000..c065581
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2023 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ *
+ * Privacy Browser PC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser PC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EDITBOOKMARKDIALOG_H
+#define EDITBOOKMARKDIALOG_H
+
+// Application headers.
+#include "structs/BookmarkStruct.h"
+
+// Qt toolkit headers.
+#include <QDialog>
+#include <QLineEdit>
+#include <QRadioButton>
+
+class EditBookmarkDialog : public QDialog
+{
+    // Include the Q_OBJECT macro.
+    Q_OBJECT
+
+public:
+    // The primary constructor.
+    explicit EditBookmarkDialog(const int bookmarkId, QIcon &currentWebsiteFavoriteIcon);
+
+signals:
+    // The signals.
+    void bookmarkSaved() const;
+
+private Q_SLOTS:
+    // The private slots.
+    void browse();
+    void save();
+
+private:
+    // The private widgets.
+    int bookmarkDatabaseId;
+    QLineEdit *bookmarkNamePointer;
+    BookmarkStruct *bookmarkStructPointer;
+    QLineEdit *bookmarkUrlPointer;
+    QRadioButton *currentFavoriteIconRadioButtonPointer;
+    QRadioButton *currentWebsiteFavoritIconRadioButtonPointer;
+    QRadioButton *customFavoriteIconRadioButtonPointer;
+};
+#endif
index 2819174099d111d048c3591719e9d542ba3713b0..98ac69a04ee9d3a1c2a70966858268c280bd0bd6 100644 (file)
@@ -29,6 +29,7 @@ struct BookmarkStruct
     int id;
     QString bookmarkName;
     QString bookmarkUrl;
+    int displayOrder;
     QIcon favoriteIcon;
 };
 #endif
index b6dc2cfb887d1165114e93a486015e03aaa655d8..01f143ce84f4d861ae7834487036aaf17b3a03a4 100644 (file)
   along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <ui version="4.0">
-  <class>AddBookmarkDialog</class>
-
-  <widget class="QWidget">
-    <layout class="QVBoxLayout">
-
-      <!-- First row. -->
-      <item>
-        <layout class="QHBoxLayout">
-          <property name="alignment">
-            <enum>Qt::AlignLeft</enum>
-          </property>
-
-          <!-- Icon. -->
-          <item>
-            <widget class="QGraphicsView"  name="favoriteIconGraphicsView">
-              <property name="sizePolicy">
-                <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                </sizepolicy>
-              </property>
-
-              <property name="maximumSize">
-                <size>
-                  <width>32</width>
-                  <height>32</height>
-                </size>
-              </property>
-
-              <property name="frameShape">
-                <enum>QFrame::NoFrame</enum>
-              </property>
-
-              <property name="alignment">
-                <set>Qt::AlignCenter</set>
-              </property>
-            </widget>
-          </item>
-
-          <!-- Spacer label. -->
-          <item>
-            <widget class="QLabel">
-              <property name="textFormat">
-                <enum>Qt::RichText</enum>
-              </property>
-
-              <property name="text">
-                <string>&amp;nbsp;</string>
-              </property>
-            </widget>
-          </item>
-
-          <!-- Bookmark name.  -->
-          <item>
-            <widget class="QLabel">
-              <property name="toolTip">
-                <string>The name of the bookmark.</string>
-              </property>
-
-              <property name="text">
-                <string>Bookmark name</string>
-              </property>
-            </widget>
-          </item>
-
-          <item>
-            <widget class="QLineEdit" name="bookmarkNameLineEdit" />
-          </item>
+    <class>AddBookmarkDialog</class>
+
+    <widget class="QWidget">
+        <layout class="QVBoxLayout">
+            <!-- Dialog body. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Favorite icon column. -->
+                    <item>
+                        <layout class="QVBoxLayout">
+                            <property name="rightMargin">
+                                <number>10</number>
+                            </property>
+
+                            <!-- First row, default favorite icon. -->
+                            <item>
+                                <widget class="QRadioButton" name="defaultFavoriteIconRadioButton">
+                                    <property name="text">
+                                        <string>Default favorite icon</string>
+                                    </property>
+
+                                    <property name="checked">
+                                        <bool>true</bool>
+                                    </property>
+
+                                    <property name="iconSize">
+                                        <size>
+                                            <height>32</height>
+                                            <width>32</width>
+                                        </size>
+                                    </property>
+                                </widget>
+                            </item>
+
+                            <!-- Second row, custom favorite icon. -->
+                            <item>
+                                <widget class="QRadioButton" name="customFavoriteIconRadioButton">
+                                    <property name="text">
+                                        <string>Custom favorite icon</string>
+                                    </property>
+
+                                    <property name="icon">
+                                        <iconset theme="globe"/>
+                                    </property>
+
+                                    <property name="iconSize">
+                                        <size>
+                                            <height>32</height>
+                                            <width>32</width>
+                                        </size>
+                                    </property>
+                                </widget>
+                            </item>
+                        </layout>
+                    </item>
+
+                    <!-- Name and URL column. -->
+                    <item>
+                        <layout class="QVBoxLayout">
+                            <!-- First row. -->
+                            <item>
+                                <layout class="QHBoxLayout">
+                                    <property name="alignment">
+                                        <enum>Qt::AlignLeft</enum>
+                                    </property>
+                                    <!-- Bookmark name.  -->
+                                    <item>
+                                        <widget class="QLabel">
+                                            <property name="toolTip">
+                                                <string>The name of the bookmark.</string>
+                                            </property>
+
+                                            <property name="text">
+                                                <string>Bookmark name</string>
+                                            </property>
+                                        </widget>
+                                    </item>
+
+                                    <item>
+                                        <widget class="QLineEdit" name="bookmarkNameLineEdit" />
+                                    </item>
+                                </layout>
+                            </item>
+
+                            <!-- Second row. -->
+                            <item>
+                                <layout class="QHBoxLayout">
+                                    <property name="alignment">
+                                        <enum>Qt::AlignLeft</enum>
+                                    </property>
+                                    <!-- Bookmark URL. -->
+                                    <item>
+                                        <widget class="QLabel">
+                                            <property name="toolTip">
+                                                <string>The URL of the bookmark.</string>
+                                            </property>
+
+                                            <property name="text">
+                                                <string>Bookmark URL</string>
+                                            </property>
+                                        </widget>
+                                    </item>
+
+                                    <item>
+                                        <widget class="QLineEdit" name="bookmarkUrlLineEdit">
+                                            <property name="sizePolicy">
+                                                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+                                                    <horstretch>0</horstretch>
+                                                    <verstretch>0</verstretch>
+                                                </sizepolicy>
+                                            </property>
+
+                                            <property name="minimumSize">
+                                                <size>
+                                                    <width>700</width>
+                                                    <height>0</height>
+                                                </size>
+                                            </property>
+                                        </widget>
+                                    </item>
+                                </layout>
+                            </item>
+                        </layout>
+                    </item>
+                </layout>
+            </item>
+
+            <!-- Spacer. -->
+            <item>
+                <spacer>
+                    <property name="orientation">
+                        <enum>Qt::Vertical</enum>
+                    </property>
+                </spacer>
+            </item>
+
+            <!-- Buttons. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Browse button. -->
+                    <item>
+                        <widget class="QPushButton" name="browseButton">
+                            <property name="text">
+                                <string>Browse</string>
+                            </property>
+
+                            <property name="icon">
+                                <iconset theme="insert-image" />
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Cancel button - dialog button box. -->
+                    <item>
+                        <widget class="QDialogButtonBox" name="dialogButtonBox">
+                            <property name="standardButtons">
+                                <set>QDialogButtonBox::Cancel</set>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
         </layout>
-      </item>
-
-      <!-- Second row. -->
-      <item>
-        <layout class="QHBoxLayout">
-          <property name="alignment">
-            <enum>Qt::AlignLeft</enum>
-          </property>
-
-          <!-- Bookmark URL. -->
-          <item>
-            <widget class="QLabel">
-              <property name="toolTip">
-                <string>The URL of the bookmark.</string>
-              </property>
-
-              <property name="text">
-                <string>Bookmark URL</string>
-              </property>
-            </widget>
-          </item>
-
-          <item>
-            <widget class="QLineEdit" name="bookmarkUrlLineEdit">
-              <property name="sizePolicy">
-                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                </sizepolicy>
-              </property>
-
-              <property name="minimumSize">
-                <size>
-                  <width>700</width>
-                  <height>0</height>
-                </size>
-              </property>
-            </widget>
-          </item>
-        </layout>
-      </item>
-
-      <!-- Spacer. -->
-      <item>
-        <spacer>
-          <property name="orientation">
-            <enum>Qt::Vertical</enum>
-          </property>
-        </spacer>
-      </item>
-
-      <!-- Dialog buttons. -->
-      <item>
-        <widget class="QDialogButtonBox" name="dialogButtonBox">
-          <property name="standardButtons">
-            <set>QDialogButtonBox::Cancel</set>
-          </property>
-        </widget>
-      </item>
-    </layout>
-  </widget>
+    </widget>
 </ui>
index 8510878b006c1e82a0c298bbce37177097ef1d09..b9355bbfb61077c2e9a3d05ff2c61b9d5e8b6f74 100644 (file)
 <ui version="4.0">
     <class>BookmarksDialog</class>
 
+    <customwidgets>
+        <customwidget>
+            <class>DraggableTreeView</class>
+            <extends>QTreeView</extends>
+            <header>widgets/DraggableTreeView.h</header>
+        </customwidget>
+    </customwidgets>
+
     <widget class="QWidget">
         <property name="geometry">
             <rect>
         <layout class="QVBoxLayout">
             <!-- Tree view. -->
             <item>
-                <widget class="QTreeView" name="treeView" />
+                <widget class="DraggableTreeView" name="draggableTreeView" />
             </item>
 
             <!-- Buttons. -->
             <item>
                 <layout class="QHBoxLayout">
+                    <!-- Add bookmark button. -->
+                    <item>
+                        <widget class="QPushButton" name="addBookmarkButton">
+                            <property name="text">
+                                <string>Add bookmark</string>
+                            </property>
+
+                            <property name="icon">
+                                <iconset theme="list-add" />
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Edit button. -->
+                    <item>
+                        <widget class="QPushButton" name="editButton">
+                            <property name="text">
+                                <string>Edit</string>
+                            </property>
+
+                            <property name="icon">
+                                <iconset theme="edit-entry" />
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Delete button. -->
+                    <item>
+                        <widget class="QPushButton" name="deleteItemsButton">
+                            <property name="text">
+                                <string>Delete items</string>
+                            </property>
+
+                            <property name="icon">
+                                <iconset theme="list-remove" />
+                            </property>
+                        </widget>
+                    </item>
+
                     <!-- Close button - dialog button box. -->
                     <item>
                         <widget class="QDialogButtonBox" name="dialogButtonBox">
diff --git a/src/uis/EditBookmarkDialog.ui b/src/uis/EditBookmarkDialog.ui
new file mode 100644 (file)
index 0000000..9dab0e8
--- /dev/null
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Copyright 2023 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+
+  Privacy Browser PC is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser PC is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<ui version="4.0">
+    <class>EditBookmarkDialog</class>
+
+    <widget class="QWidget">
+        <layout class="QVBoxLayout">
+            <!-- Dialog body. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Favorite icon column. -->
+                    <item>
+                        <layout class="QVBoxLayout">
+                            <property name="rightMargin">
+                                <number>10</number>
+                            </property>
+
+                            <!-- First row, current favorite icon. -->
+                            <item>
+                                <widget class="QRadioButton" name="currentFavoriteIconRadioButton">
+                                    <property name="text">
+                                        <string>Current favorite icon</string>
+                                    </property>
+
+                                    <property name="checked">
+                                        <bool>true</bool>
+                                    </property>
+
+                                    <property name="iconSize">
+                                        <size>
+                                            <height>32</height>
+                                            <width>32</width>
+                                        </size>
+                                    </property>
+                                </widget>
+                            </item>
+
+                            <!-- Second row, current website favorite icon. -->
+                            <item>
+                                <widget class="QRadioButton" name="currentWebsiteFavoriteIconRadioButton">
+                                    <property name="text">
+                                        <string>Current website favorite icon</string>
+                                    </property>
+
+                                    <property name="iconSize">
+                                        <size>
+                                            <height>32</height>
+                                            <width>32</width>
+                                        </size>
+                                    </property>
+                                </widget>
+                            </item>
+
+                            <!-- Third row, custom favorite icon. -->
+                            <item>
+                                <widget class="QRadioButton" name="customFavoriteIconRadioButton">
+                                    <property name="text">
+                                        <string>Custom favorite icon</string>
+                                    </property>
+
+                                    <property name="icon">
+                                        <iconset theme="globe"/>
+                                    </property>
+
+                                    <property name="iconSize">
+                                        <size>
+                                            <height>32</height>
+                                            <width>32</width>
+                                        </size>
+                                    </property>
+                                </widget>
+                            </item>
+                        </layout>
+                    </item>
+
+                    <!-- Name and URL column. -->
+                    <item>
+                        <layout class="QVBoxLayout">
+                            <!-- First row. -->
+                            <item>
+                                <layout class="QHBoxLayout">
+                                    <property name="alignment">
+                                        <enum>Qt::AlignLeft</enum>
+                                    </property>
+                                    <!-- Bookmark name.  -->
+                                    <item>
+                                        <widget class="QLabel">
+                                            <property name="toolTip">
+                                                <string>The name of the bookmark.</string>
+                                            </property>
+
+                                            <property name="text">
+                                                <string>Bookmark name</string>
+                                            </property>
+                                        </widget>
+                                    </item>
+
+                                    <item>
+                                        <widget class="QLineEdit" name="bookmarkNameLineEdit" />
+                                    </item>
+                                </layout>
+                            </item>
+
+                            <!-- Second row. -->
+                            <item>
+                                <layout class="QHBoxLayout">
+                                    <property name="alignment">
+                                        <enum>Qt::AlignLeft</enum>
+                                    </property>
+                                    <!-- Bookmark URL. -->
+                                    <item>
+                                        <widget class="QLabel">
+                                            <property name="toolTip">
+                                                <string>The URL of the bookmark.</string>
+                                            </property>
+
+                                            <property name="text">
+                                                <string>Bookmark URL</string>
+                                            </property>
+                                        </widget>
+                                    </item>
+
+                                    <item>
+                                        <widget class="QLineEdit" name="bookmarkUrlLineEdit">
+                                            <property name="sizePolicy">
+                                                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+                                                    <horstretch>0</horstretch>
+                                                    <verstretch>0</verstretch>
+                                                </sizepolicy>
+                                            </property>
+
+                                            <property name="minimumSize">
+                                                <size>
+                                                    <width>700</width>
+                                                    <height>0</height>
+                                                </size>
+                                            </property>
+                                        </widget>
+                                    </item>
+                                </layout>
+                            </item>
+                        </layout>
+                    </item>
+                </layout>
+            </item>
+
+            <!-- Spacer. -->
+            <item>
+                <spacer>
+                    <property name="orientation">
+                        <enum>Qt::Vertical</enum>
+                    </property>
+                </spacer>
+            </item>
+
+            <!-- Buttons. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Browse button. -->
+                    <item>
+                        <widget class="QPushButton" name="browseButton">
+                            <property name="text">
+                                <string>Browse</string>
+                            </property>
+
+                            <property name="icon">
+                                <iconset theme="insert-image" />
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Cancel button - dialog button box. -->
+                    <item>
+                        <widget class="QDialogButtonBox" name="dialogButtonBox">
+                            <property name="standardButtons">
+                                <set>QDialogButtonBox::Save | QDialogButtonBox::Cancel</set>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+        </layout>
+    </widget>
+</ui>
index a391b8975a77202e0d1633894d0e840845446647..d237afbe12f8ed3025f4902e58d85207cea5a6fc 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+# Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
 #
 # This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 #
@@ -18,6 +18,7 @@
 
 # List the sources to include in the executable.
 target_sources(privacybrowser PRIVATE
-    TabWidget.cpp
+    DraggableTreeView.cpp
     PrivacyWebEngineView.cpp
+    TabWidget.cpp
 )
diff --git a/src/widgets/DraggableTreeView.cpp b/src/widgets/DraggableTreeView.cpp
new file mode 100644 (file)
index 0000000..1fa07a5
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2023 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ *
+ * Privacy Browser PC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser PC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Application headers.
+#include "DraggableTreeView.h"
+#include "databases/BookmarksDatabase.h"
+#include "dialogs/BookmarksDialog.h"
+
+// Qt toolkit headers.
+#include <QDebug>
+#include <QDropEvent>
+#include <QList>
+
+// Construct the class.
+DraggableTreeView::DraggableTreeView(QWidget *parentWidget) : QTreeView(parentWidget) {}
+
+// Handle drop events.
+void DraggableTreeView::dropEvent(QDropEvent *dropEvent)
+{
+    // Get the list of currently selected items that are moving.
+    QList<QModelIndex> indexesMovingList = selectedIndexes();
+
+    // Create a list of database IDs that are moving.
+    QList<int> *databaseIdsMovingListPointer = new QList<int>;
+
+    // Populate the list of moving database IDs.
+    for (const QModelIndex &modelIndex : indexesMovingList)
+    {
+        // Only process model indexes from the bookmark name column (by default, there will be model indexes from all the visible columns in the list).
+        if (modelIndex.column() == BookmarksDialog::BOOKMARK_NAME_COLUMN)
+            databaseIdsMovingListPointer->append(modelIndex.siblingAtColumn(BookmarksDialog::DATABASE_ID_COLUMN).data().toInt());
+    }
+
+    // Get the drop position.
+    int dropPosition = dropIndicatorPosition();
+
+    // Get the drop model index.
+    QModelIndex dropModelIndex = indexAt(dropEvent->pos());
+
+    // Get the drop display order.
+    int dropDisplayOrder = dropModelIndex.siblingAtColumn(BookmarksDialog::DISPLAY_ORDER).data().toInt();
+
+    // Process the move according to the drop position.
+    switch (dropPosition)
+    {
+        case QAbstractItemView::OnItem:
+            // TODO  Implement for moving into a folder.
+            break;
+
+        case QAbstractItemView::AboveItem:
+        {
+            // Get a list of all the bookmarks except those selected.
+            QList<BookmarkStruct> *bookmarksExceptSelectedListPointer = BookmarksDatabase::getBookmarksExcept(databaseIdsMovingListPointer);
+
+            // Initialize a new display order tracker.
+            int newDisplayOrder = 0;
+
+            // Move the bookmarks.
+            for (const BookmarkStruct &bookmarkStruct : *bookmarksExceptSelectedListPointer)
+            {
+                // Check to see if this is the drop display order.
+                if (bookmarkStruct.displayOrder == dropDisplayOrder)
+                {
+                    // Add all of the bookmarks being moved to this point.
+                    for (const int databaseId : *databaseIdsMovingListPointer)
+                    {
+                        // Update the display order for each bookmark.
+                        BookmarksDatabase::updateDisplayOrder(databaseId, newDisplayOrder);
+
+                        // Increment the new display order.
+                        ++newDisplayOrder;
+                    }
+                }
+
+                // Set the bookmark's display order if it has changed.
+                if (bookmarkStruct.displayOrder != newDisplayOrder)
+                    BookmarksDatabase::updateDisplayOrder(bookmarkStruct.id, newDisplayOrder);
+
+                // Increment the new display order.
+                ++newDisplayOrder;
+            }
+
+            break;
+        }
+
+        case QAbstractItemView::BelowItem:
+        {
+            // Get a list of all the bookmarks except those selected.
+            QList<BookmarkStruct> *bookmarksExceptSelectedListPointer = BookmarksDatabase::getBookmarksExcept(databaseIdsMovingListPointer);
+
+            // Initialize a new display order tracker.
+            int newDisplayOrder = 0;
+
+            // Move the bookmarks.
+            for (const BookmarkStruct &bookmarkStruct : *bookmarksExceptSelectedListPointer)
+            {
+                // Set the bookmark's display order if it has changed.
+                if (bookmarkStruct.displayOrder != newDisplayOrder)
+                    BookmarksDatabase::updateDisplayOrder(bookmarkStruct.id, newDisplayOrder);
+
+                // Increment the new display order.
+                ++newDisplayOrder;
+
+                // Check to see if this is the drop display order.
+                if (bookmarkStruct.displayOrder == dropDisplayOrder)
+                {
+                    // Add all of the bookmarks being moved to this point.
+                    for (const int databaseId : *databaseIdsMovingListPointer)
+                    {
+                        // Update the display order for each bookmark.
+                        BookmarksDatabase::updateDisplayOrder(databaseId, newDisplayOrder);
+
+                        // Increment the new display order.
+                        ++newDisplayOrder;
+                    }
+                }
+            }
+
+            break;
+        }
+
+        case QAbstractItemView::OnViewport:
+
+            // Get a list of all the bookmarks except those selected.
+            QList<BookmarkStruct> *bookmarksExceptSelectedListPointer = BookmarksDatabase::getBookmarksExcept(databaseIdsMovingListPointer);
+
+            // Initialize a new display order tracker.
+            int newDisplayOrder = 0;
+
+            // Move the bookmarks.
+            for (const BookmarkStruct &bookmarkStruct : *bookmarksExceptSelectedListPointer)
+            {
+                // Set the bookmark's display order if it has changed.
+                if (bookmarkStruct.displayOrder != newDisplayOrder)
+                    BookmarksDatabase::updateDisplayOrder(bookmarkStruct.id, newDisplayOrder);
+
+                // Increment the new display order.
+                ++newDisplayOrder;
+            }
+
+            // Add all of the bookmarks being moved to the end of the list.
+            for (const int databaseId : *databaseIdsMovingListPointer)
+            {
+                // Update the display order for each bookmark.
+                BookmarksDatabase::updateDisplayOrder(databaseId, newDisplayOrder);
+
+                // Increment the new display order.
+                ++newDisplayOrder;
+            }
+            break;
+    }
+
+    // Emit the bookmarks moved signal.
+    emit bookmarksMoved();
+}
diff --git a/src/widgets/DraggableTreeView.h b/src/widgets/DraggableTreeView.h
new file mode 100644 (file)
index 0000000..f520ed3
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ *
+ * Privacy Browser PC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser PC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRAGGABLETREEVIEW_H
+#define DRAGGABLETREEVIEW_H
+
+// Qt toolkit headers.
+#include <QTreeView>
+
+class DraggableTreeView : public QTreeView
+{
+    // Include the Q_OBJECT macro.
+    Q_OBJECT
+
+public:
+    // The default contructor.
+    explicit DraggableTreeView(QWidget *parentWidget = nullptr);
+
+signals:
+    // The signals.
+    void bookmarksMoved() const;
+
+protected:
+    void dropEvent(QDropEvent *event) override;
+};
+#endif
index c8c766da4e2586ead8fbfa4bf23f620cf0339f9e..dda65d9c466a4cb97a382481cc62188d9904e51a 100644 (file)
@@ -73,7 +73,7 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     QAction *backActionPointer = KStandardAction::back(this, SLOT(back()), actionCollectionPointer);
     QAction *forwardActionPointer = KStandardAction::forward(this, SLOT(forward()), actionCollectionPointer);
     KStandardAction::home(this, SLOT(home()), actionCollectionPointer);
-    KStandardAction::addBookmark(this, SLOT(addBookmark()), actionCollectionPointer);
+    KStandardAction::addBookmark(this, SLOT(showAddBookmarkDialog()), actionCollectionPointer);
     QAction *editBookmarksActionPointer = KStandardAction::editBookmarks(this, SLOT(editBookmarks()), actionCollectionPointer);
     KStandardAction::preferences(this, SLOT(showSettingsDialog()), actionCollectionPointer);
     KStandardAction::find(this, SLOT(showFindTextActions()), actionCollectionPointer);
@@ -509,6 +509,12 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     bookmarksMenuCurrentActionList = QList<QAction*>();
     bookmarksToolBarCurrentActionList = QList<QAction*>();
 
+    // Set the bookmarks toolbar context menu policy.
+    bookmarksToolBarPointer->setContextMenuPolicy(Qt::CustomContextMenu);
+
+    // Show the custom bookmark context menu when requested.
+    connect(bookmarksToolBarPointer, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBookmarkContextMenu(const QPoint&)));
+
     // Populate the bookmarks.
     populateBookmarks();
 
@@ -525,15 +531,6 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
         tabWidgetPointer->loadInitialWebsite();
 }
 
-void BrowserWindow::addBookmark() const
-{
-    // Instantiate an add bookmark dialog.
-    AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl(), tabWidgetPointer->getCurrentTabFavoritIcon());
-
-    // Show the dialog.
-    addBookmarkDialogPointer->show();
-}
-
 void BrowserWindow::addOrEditDomainSettings() const
 {
     // Remove the focus from the URL line edit.
@@ -598,7 +595,7 @@ void BrowserWindow::decrementZoom()
 void BrowserWindow::editBookmarks() const
 {
     // Instantiate an edit bookmarks dialog.
-    BookmarksDialog *bookmarksDialogPointer = new BookmarksDialog();
+    BookmarksDialog *bookmarksDialogPointer = new BookmarksDialog(tabWidgetPointer->getCurrentTabFavoritIcon());
 
     // Update the displayed bookmarks when edited.
     connect(bookmarksDialogPointer, SIGNAL(bookmarkUpdated()), this, SLOT(populateBookmarks()));
@@ -868,6 +865,23 @@ void BrowserWindow::reloadAndBypassCache() const
     tabWidgetPointer->refresh();
 }
 
+void BrowserWindow::showAddBookmarkDialog() const
+{
+    // Instantiate an add bookmark dialog.
+    AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl(), tabWidgetPointer->getCurrentTabFavoritIcon());
+
+    // Update the displayed bookmarks when a new one is added.
+    connect(addBookmarkDialogPointer, SIGNAL(bookmarkAdded()), this, SLOT(populateBookmarks()));
+
+    // Show the dialog.
+    addBookmarkDialogPointer->show();
+}
+
+void BrowserWindow::showBookmarkContextMenu(const QPoint&) const
+{
+    qDebug() << "Show the bookmark context menu.";
+}
+
 void BrowserWindow::showCookiesDialog()
 {
     // Remove the focus from the URL line edit.
index 49cb198307f40c7e6ddc2cc6b0005834a84b1e80..92cdc8eca691bbf59c283e7c1b5cc104383cdcf3 100644 (file)
@@ -51,7 +51,6 @@ public:
 
 private Q_SLOTS:
     // The private slots.
-    void addBookmark() const;
     void addOrEditDomainSettings() const;
     void back() const;
     void clearUrlLineEditFocus() const;
@@ -71,6 +70,8 @@ private Q_SLOTS:
     void populateBookmarks();
     void refresh() const;
     void reloadAndBypassCache() const;
+    void showAddBookmarkDialog() const;
+    void showBookmarkContextMenu(const QPoint&) const;
     void showCookiesDialog();
     void showDownloadLocationBrowseDialog() const;
     void showDomainSettingsDialog() const;