X-Git-Url: https://gitweb.stoutner.com/?p=PrivacyBrowserPC.git;a=blobdiff_plain;f=src%2Fdialogs%2FBookmarksDialog.cpp;fp=src%2Fdialogs%2FBookmarksDialog.cpp;h=be150cc9e4f5d36ef3ec4d5ba4a885529a325503;hp=4dc66ee873a04b892564b5e35b0f3a901c5551b9;hb=29dbafaca706ea6a34cd881060ebf680378f39b4;hpb=3331f3d1a5d8924a67bcac2a2c842e15a421fea2 diff --git a/src/dialogs/BookmarksDialog.cpp b/src/dialogs/BookmarksDialog.cpp index 4dc66ee..be150cc 100644 --- a/src/dialogs/BookmarksDialog.cpp +++ b/src/dialogs/BookmarksDialog.cpp @@ -22,7 +22,9 @@ #include "ui_BookmarksDialog.h" #include "databases/BookmarksDatabase.h" #include "dialogs/AddBookmarkDialog.h" +#include "dialogs/AddFolderDialog.h" #include "dialogs/EditBookmarkDialog.h" +#include "dialogs/EditFolderDialog.h" // KDE Frameworks headers. #include @@ -32,7 +34,8 @@ #include // Construct the class. -BookmarksDialog::BookmarksDialog(QIcon currentWebsiteFavorieIcon) : QDialog(nullptr), websiteFavoriteIcon(currentWebsiteFavorieIcon) +BookmarksDialog::BookmarksDialog(QString currentWebsiteTitle, QString currentWebsiteUrl, QIcon currentWebsiteFavorieIcon) : + QDialog(nullptr), websiteFavoriteIcon(currentWebsiteFavorieIcon), websiteTitle(currentWebsiteTitle), websiteUrl(currentWebsiteUrl) { // Set the dialog window title. setWindowTitle(i18nc("The bookmarks dialog window title", "Bookmarks")); @@ -71,13 +74,14 @@ BookmarksDialog::BookmarksDialog(QIcon currentWebsiteFavorieIcon) : QDialog(null treeSelectionModelPointer = draggableTreeViewPointer->selectionModel(); // Listen for selection changes. - connect(treeSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi())); + connect(treeSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateSelection())); // Repopulate the bookmarks when they are moved. connect(draggableTreeViewPointer, SIGNAL(bookmarksMoved()), this, SLOT(refreshBookmarks())); // Get handles for the buttons. QPushButton *addBookmarkButtonPointer = bookmarksDialogUi.addBookmarkButton; + QPushButton *addFolderButtonPointer = bookmarksDialogUi.addFolderButton; editButtonPointer = bookmarksDialogUi.editButton; deleteItemsButtonPointer = bookmarksDialogUi.deleteItemsButton; QDialogButtonBox *dialogButtonBoxPointer = bookmarksDialogUi.dialogButtonBox; @@ -85,6 +89,7 @@ BookmarksDialog::BookmarksDialog(QIcon currentWebsiteFavorieIcon) : QDialog(null // Connect the buttons. connect(addBookmarkButtonPointer, SIGNAL(clicked()), this, SLOT(showAddBookmarkDialog())); + connect(addFolderButtonPointer, SIGNAL(clicked()), this, SLOT(showAddFolderDialog())); connect(editButtonPointer, SIGNAL(clicked()), this, SLOT(showEditDialog())); connect(deleteItemsButtonPointer, SIGNAL(clicked()), this, SLOT(deleteItems())); connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject())); @@ -101,16 +106,32 @@ BookmarksDialog::BookmarksDialog(QIcon currentWebsiteFavorieIcon) : QDialog(null void BookmarksDialog::deleteItems() const { + // Create a parent folder ID standard C++ list (which can be sorted and from which duplicates can be removed). + std::list parentFolderIdList; + // Get the list of selected model indexes. QList selectedModelIndexList = treeSelectionModelPointer->selectedRows(DATABASE_ID_COLUMN); // Delete each of the bookmarks. for (const QModelIndex &modelIndex : selectedModelIndexList) { + // Add the parent folder ID to the list. + parentFolderIdList.push_back(modelIndex.parent().siblingAtColumn(FOLDER_ID_COLUMN).data().toDouble()); + // Delete the bookmark. BookmarksDatabase::deleteBookmark(modelIndex.data().toInt()); } + // Sort the parent folder ID. + parentFolderIdList.sort(); + + // Remove duplicates from the parent folder ID list. + parentFolderIdList.unique(); + + // Update the folder contents display order for each folder with a deleted bookmark. + for (const double parentFolderId : parentFolderIdList) + BookmarksDatabase::updateFolderContentsDisplayOrder(parentFolderId); + // Repopulate the bookmarks in this dialog populateBookmarks(); @@ -124,38 +145,90 @@ void BookmarksDialog::populateBookmarks() const treeModelPointer->clear(); // Set the column count. - treeModelPointer->setColumnCount(4); + treeModelPointer->setColumnCount(6); - // 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")); + // Set the tree header data. + treeModelPointer->setHeaderData(NAME_COLUMN, Qt::Horizontal, i18nc("The bookmark Name header.", "Name")); + treeModelPointer->setHeaderData(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); + draggableTreeViewPointer->setColumnHidden(DISPLAY_ORDER_COLUMN, true); + draggableTreeViewPointer->setColumnHidden(IS_FOLDER_COLUMN, true); + draggableTreeViewPointer->setColumnHidden(FOLDER_ID_COLUMN, true); + + // Create a bookmarks root item list. + QList bookmarksRootItemList; + + // Create the root items. + QStandardItem *rootItemNamePointer = new QStandardItem(QIcon::fromTheme("bookmarks"), i18nc("The bookmarks root tree widget name", "Bookmarks")); + QStandardItem *rootItemUrlPointer = new QStandardItem(QLatin1String("")); + QStandardItem *rootItemDatabaseIdPonter = new QStandardItem(QLatin1String("-1")); // The root item doesn't have a database ID. + QStandardItem *rootItemDisplayOrderPointer = new QStandardItem(QLatin1String("-1")); // The root item doesn't have a display order. + QStandardItem *rootItemIsFolderPointer = new QStandardItem(QLatin1String("1")); + QStandardItem *rootItemFolderIdPointer = new QStandardItem(QLatin1String("0")); + + // Enable dropping on the root name column. + rootItemNamePointer->setDropEnabled(true); + + // Disable dropping on the URL. + rootItemUrlPointer->setDropEnabled(false); + + // Disable dragging of the bookmarks root item. + rootItemNamePointer->setDragEnabled(false); + rootItemUrlPointer->setDragEnabled(false); + + // Disable selecting the URL. + rootItemUrlPointer->setSelectable(false); - // Get the list of bookmarks. - std::list *bookmarksListPointer = BookmarksDatabase::getBookmarks(); + // Populate the bookmarks root item list. + bookmarksRootItemList.append(rootItemNamePointer); + bookmarksRootItemList.append(rootItemUrlPointer); + bookmarksRootItemList.append(rootItemDatabaseIdPonter); + bookmarksRootItemList.append(rootItemDisplayOrderPointer); + bookmarksRootItemList.append(rootItemIsFolderPointer); + bookmarksRootItemList.append(rootItemFolderIdPointer); + + // Add the bookmarks root item to the tree. + treeModelPointer->appendRow(bookmarksRootItemList); + + // Populate the subfolders, starting with the root folder ID (`0`). + populateSubfolders(rootItemNamePointer, 0); + + // Expand all the folder. + draggableTreeViewPointer->expandAll(); + + // Update the UI. + updateUi(); +} + +void BookmarksDialog::populateSubfolders(QStandardItem *folderItemNamePointer, const double folderId) const +{ + // Get the folder contents. + QList *folderContentsListPointer = BookmarksDatabase::getFolderContents(folderId); // Populate the bookmarks tree view. - for (const BookmarkStruct &bookmarkStruct : *bookmarksListPointer) + for (const BookmarkStruct &bookmarkStruct : *folderContentsListPointer) { - // Create a list for the bookmark items. + // Create a bookmark item list. QList bookmarkItemList; // Create the bookmark items. - 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)); - + QStandardItem *nameItemPointer = new QStandardItem(bookmarkStruct.favoriteIcon, bookmarkStruct.name); + QStandardItem *urlItemPointer = new QStandardItem(bookmarkStruct.url); + QStandardItem *databaseIdItemPointer = new QStandardItem(QString::number(bookmarkStruct.databaseId)); + QStandardItem *displayOrderItemPointer = new QStandardItem(QString::number(bookmarkStruct.displayOrder)); + QStandardItem *isFolderItemPointer = new QStandardItem(QString::number(bookmarkStruct.isFolder)); + QStandardItem *folderIdItemPointer = new QStandardItem(QString::number(bookmarkStruct.folderId, 'f', 0)); // Format the folder ID as a floating point with no trailing zeros. + + // Enable dragging and dropping of the name column. nameItemPointer->setDragEnabled(true); - nameItemPointer->setDropEnabled(true); - // Disable dragging the URL. - urlItemPointer->setDragEnabled(false); + // Only allow dropping on the name if this is a folder. + nameItemPointer->setDropEnabled(bookmarkStruct.isFolder); - // Disable dropping on the URL. For some reason this doesn't work. + // Disable dragging and dropping on the URL. + urlItemPointer->setDragEnabled(false); urlItemPointer->setDropEnabled(false); // Disable selecting the URL. @@ -164,15 +237,18 @@ void BookmarksDialog::populateBookmarks() const // Populate the bookmark item list. bookmarkItemList.append(nameItemPointer); bookmarkItemList.append(urlItemPointer); - bookmarkItemList.append(idItemPointer); - bookmarkItemList.append(displayOrderPointer); + bookmarkItemList.append(databaseIdItemPointer); + bookmarkItemList.append(displayOrderItemPointer); + bookmarkItemList.append(isFolderItemPointer); + bookmarkItemList.append(folderIdItemPointer); - // Add the bookmark to the tree. - treeModelPointer->appendRow(bookmarkItemList); - } + // Add the bookmark to the parent folder. + folderItemNamePointer->appendRow(bookmarkItemList); - // Update the UI. - updateUi(); + // Populate subfolders if this item is a folder. + if (bookmarkStruct.isFolder) + populateSubfolders(nameItemPointer, bookmarkStruct.folderId); + } } void BookmarksDialog::refreshBookmarks() const @@ -184,10 +260,68 @@ void BookmarksDialog::refreshBookmarks() const emit bookmarkUpdated(); } +void BookmarksDialog::selectSubfolderContents(const QModelIndex &parentModelIndex) const +{ + // Get the index model. + const QAbstractItemModel *modelIndexAbstractItemPointer = parentModelIndex.model(); + + // Get the number of items in the folder. + int numberOfChildrenInFolder = modelIndexAbstractItemPointer->rowCount(parentModelIndex); + + // Select any child items. + if (numberOfChildrenInFolder > 0) + { + // Select the contents of any subfolders. + for (int i = 0; i < numberOfChildrenInFolder; ++i) + { + // Get the child model index. + QModelIndex childModelIndex = modelIndexAbstractItemPointer->index(i, 0, parentModelIndex); + + // Select the subfolder contents if it is a folder. + if (childModelIndex.siblingAtColumn(IS_FOLDER_COLUMN).data().toBool()) + selectSubfolderContents(childModelIndex); + } + + // Get the first and last child model indexes. + QModelIndex firstChildModelIndex = modelIndexAbstractItemPointer->index(0, 0, parentModelIndex); + QModelIndex lastChildModelIndex = modelIndexAbstractItemPointer->index((numberOfChildrenInFolder - 1), 0, parentModelIndex); + + // Create an item selection that includes all the child items. + QItemSelection folderChildItemsSelection = QItemSelection(firstChildModelIndex, lastChildModelIndex); + + // Get the current selection. + QItemSelection currentSelection = treeSelectionModelPointer->selection(); + + // Combine the current selection and the folder child items selection. + currentSelection.merge(folderChildItemsSelection, QItemSelectionModel::SelectCurrent); + + // Selected the updated list of items. + treeSelectionModelPointer->select(currentSelection, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } +} + void BookmarksDialog::showAddBookmarkDialog() const { + // Return the most recently selected index. + QModelIndex currentIndex = treeSelectionModelPointer->currentIndex(); + + // Instantiate a parent folder ID. + double parentFolderId; + + // Get the parent folder ID. + if (currentIndex.siblingAtColumn(IS_FOLDER_COLUMN).data().toInt() == 1) // The current index is a folder. + { + // Store the parent folder ID. + parentFolderId = currentIndex.siblingAtColumn(FOLDER_ID_COLUMN).data().toDouble(); + } + else // The current index is not a folder. + { + // Store the parent folder ID of the folder that contains the bookmark. + parentFolderId = currentIndex.parent().siblingAtColumn(FOLDER_ID_COLUMN).data().toDouble(); + } + // Instantiate an add bookmark dialog. - AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(QLatin1String(""), QLatin1String(""), websiteFavoriteIcon); + AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(websiteTitle, websiteUrl, websiteFavoriteIcon, parentFolderId); // Update the displayed bookmarks when a new one is added. connect(addBookmarkDialogPointer, SIGNAL(bookmarkAdded()), this, SLOT(refreshBookmarks())); @@ -196,19 +330,64 @@ void BookmarksDialog::showAddBookmarkDialog() const addBookmarkDialogPointer->show(); } +void BookmarksDialog::showAddFolderDialog() const +{ + // Get the most recently selected index. + QModelIndex currentIndex = treeSelectionModelPointer->currentIndex(); + + // Instantiate a parent folder ID. + double parentFolderId; + + // Get the parent folder ID. + if (currentIndex.siblingAtColumn(IS_FOLDER_COLUMN).data().toInt() == 1) // The current index is a folder. + { + // Store the parent folder ID. + parentFolderId = currentIndex.siblingAtColumn(FOLDER_ID_COLUMN).data().toDouble(); + } + else // The current index is not a folder. + { + // Store the parent folder ID of the folder that contains the bookmark. + parentFolderId = currentIndex.parent().siblingAtColumn(FOLDER_ID_COLUMN).data().toDouble(); + } + + // Instantiate an add folder dialog. + AddFolderDialog *addFolderDialogPointer = new AddFolderDialog(websiteFavoriteIcon, parentFolderId); + + // Update the displayed bookmarks when a folder is added. + connect(addFolderDialogPointer, SIGNAL(folderAdded()), this, SLOT(refreshBookmarks())); + + // Show the dialog. + addFolderDialogPointer->show(); +} + 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); + // Check to see if the selected item is a folder. + if (currentIndex.siblingAtColumn(IS_FOLDER_COLUMN).data().toInt() == 1) // The selected item is a folder. + { + // Instantiate an edit folder dialog. + QDialog *editFolderDialogPointer = new EditFolderDialog(currentIndex.siblingAtColumn(DATABASE_ID_COLUMN).data().toInt(), websiteFavoriteIcon); - // Show the dialog. - editBookmarkDialogPointer->show(); + // Show the dialog. + editFolderDialogPointer->show(); - // Process bookmark events. - connect(editBookmarkDialogPointer, SIGNAL(bookmarkSaved()), this, SLOT(refreshBookmarks())); + // Update the bookmarks UI. + connect(editFolderDialogPointer, SIGNAL(folderSaved()), this, SLOT(refreshBookmarks())); + } + else // The selected item is a bookmark. + { + // Instantiate an edit bookmark dialog. + QDialog *editBookmarkDialogPointer = new EditBookmarkDialog(currentIndex.siblingAtColumn(DATABASE_ID_COLUMN).data().toInt(), websiteFavoriteIcon); + + // Show the dialog. + editBookmarkDialogPointer->show(); + + // Update the bookmarks UI. + connect(editBookmarkDialogPointer, SIGNAL(bookmarkSaved()), this, SLOT(refreshBookmarks())); + } } void BookmarksDialog::updateBookmarkFromTree(QStandardItem *modifiedStandardItem) @@ -223,7 +402,7 @@ void BookmarksDialog::updateBookmarkFromTree(QStandardItem *modifiedStandardItem int databaseId = databaseIdModelIndex.data().toInt(); // Check to see if the bookmark name or the URL was edited. - if (modifiedStandardItem->column() == BOOKMARK_NAME_COLUMN) // The bookmark name was edited. + if (modifiedStandardItem->column() == NAME_COLUMN) // The bookmark name was edited. { // Update the bookmark name. BookmarksDatabase::updateBookmarkName(databaseId, modifiedStandardItem->text()); @@ -238,17 +417,62 @@ void BookmarksDialog::updateBookmarkFromTree(QStandardItem *modifiedStandardItem emit bookmarkUpdated(); } +void BookmarksDialog::updateSelection() const +{ + // Set the status of the buttons. + if (treeSelectionModelPointer->hasSelection()) // A bookmark or folder is selected. + { + // Get the list of selected model indexes. + QModelIndexList selectedRowsModelIndexList = treeSelectionModelPointer->selectedRows(); + + // Check to see if each selected item is a folder. + for(QModelIndex modelIndex : selectedRowsModelIndexList) + { + // If it is a folder, select all the children bookmarks. + if (modelIndex.siblingAtColumn(IS_FOLDER_COLUMN).data().toBool()) + selectSubfolderContents(modelIndex); + } + } + + // Update the UI. + updateUi(); +} + 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); + // Get the currently selected index. + QModelIndex currentSelectedIndex = treeSelectionModelPointer->currentIndex(); + + // Get the list of selected model indexes. + QModelIndexList selectedRowsModelIndexList = treeSelectionModelPointer->selectedRows(); + + // Get the number of selected rows. + int numberOfSelectedRows = selectedRowsModelIndexList.count(); + + // Enable the edit button if a folder or only one bookmark is selected. + editButtonPointer->setEnabled(currentSelectedIndex.siblingAtColumn(IS_FOLDER_COLUMN).data().toBool() || (numberOfSelectedRows == 1)); + + // Check if the root folder is selected. + if (treeSelectionModelPointer->isRowSelected(0)) + { + // Disable the edit button. + editButtonPointer->setEnabled(false); + + // Decrease the number of selected rows by 1. + --numberOfSelectedRows; + } + + // Enabled the delete button if at least one real bookmark or folder is selected. + deleteItemsButtonPointer->setEnabled(numberOfSelectedRows > 0); // Update the delete items button text. - deleteItemsButtonPointer->setText(i18ncp("Delete items button populated text.", "Delete %1 item", "Delete %1 items", treeSelectionModelPointer->selectedRows().count())); + if (numberOfSelectedRows > 0) + deleteItemsButtonPointer->setText(i18ncp("Delete items button populated text.", "Delete %1 item", "Delete %1 items", numberOfSelectedRows)); + else + deleteItemsButtonPointer->setText(i18nc("Delete items button default text", "Delete items")); } else // Nothing is selected. {