--- /dev/null
+/*
+ * 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();
+}