From: Soren Stoutner Date: Tue, 21 Jun 2022 20:43:00 +0000 (-0700) Subject: Add a durable cookies dialog. X-Git-Tag: v0.1~27 X-Git-Url: https://gitweb.stoutner.com/?a=commitdiff_plain;h=adf448e4cca7b96f6db9fc2048e9a64fa24a9bba;p=PrivacyBrowserPC.git Add a durable cookies dialog. --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fd274ce..335a27d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,7 @@ ki18n_wrap_ui(privacy-browser uis/BrowserView.ui uis/CookiesDialog.ui uis/DomainSettingsDialog.ui + uis/DurableCookiesDialog.ui uis/SettingsGeneral.ui uis/SettingsPrivacy.ui ) @@ -63,6 +64,7 @@ target_link_libraries(privacy-browser # Add the subdirectories. add_subdirectory(databases) +add_subdirectory(delegates) add_subdirectory(dialogs) add_subdirectory(filters) add_subdirectory(helpers) diff --git a/src/databases/CookiesDatabase.cpp b/src/databases/CookiesDatabase.cpp index adc4f1b..a992909 100644 --- a/src/databases/CookiesDatabase.cpp +++ b/src/databases/CookiesDatabase.cpp @@ -146,6 +146,33 @@ void CookiesDatabase::addCookie(const QNetworkCookie &cookie) } } +int CookiesDatabase::cookieCount() +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Instantiate a count cookies query. + QSqlQuery countCookiesQuery(cookiesDatabase); + + // Set the query to be forward only. + countCookiesQuery.setForwardOnly(true); + + // Prepare the query. + countCookiesQuery.prepare("SELECT " + _ID + " FROM " + COOKIES_TABLE); + + // Execute the query. + countCookiesQuery.exec(); + + // Move to the last row. + countCookiesQuery.last(); + + // Get the number of rows (which is zero based). + int numberOfCookies = countCookiesQuery.at() + 1; + + // Return the number of cookies. + return numberOfCookies; +} + void CookiesDatabase::deleteAllCookies() { // Get a handle for the cookies database. @@ -224,6 +251,45 @@ QList* CookiesDatabase::getCookies() return cookieListPointer; } +QNetworkCookie* CookiesDatabase::getCookieById(const int &id) +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Instantiate a cookie query. + QSqlQuery cookieQuery(cookiesDatabase); + + // Set the query to be forward only. + cookieQuery.setForwardOnly(true); + + // Prepare the cookies query. + cookieQuery.prepare("SELECT * FROM " + COOKIES_TABLE + " WHERE " + _ID + " = :id"); + + // Bind the values. + cookieQuery.bindValue(":id", id); + + // Execute the query. + cookieQuery.exec(); + + // Move to the first entry. + cookieQuery.first(); + + // Create a cookie. + QNetworkCookie *cookiePointer = new QNetworkCookie(); + + // Populate the cookie. + cookiePointer->setDomain(cookieQuery.value(DOMAIN).toString()); + cookiePointer->setName(cookieQuery.value(NAME).toString().toUtf8()); + cookiePointer->setPath(cookieQuery.value(PATH).toString()); + cookiePointer->setExpirationDate(QDateTime::fromString(cookieQuery.value(EXPIRATION_DATE).toString(), Qt::ISODate)); + cookiePointer->setHttpOnly(cookieQuery.value(HTTP_ONLY).toBool()); + cookiePointer->setSecure(cookieQuery.value(SECURE).toBool()); + cookiePointer->setValue(cookieQuery.value(VALUE).toString().toUtf8()); + + // Return the cookie. + return cookiePointer; +} + bool CookiesDatabase::isDurable(const QNetworkCookie &cookie) { // Get a handle for the cookies database. diff --git a/src/databases/CookiesDatabase.h b/src/databases/CookiesDatabase.h index 6fcae89..76e788c 100644 --- a/src/databases/CookiesDatabase.h +++ b/src/databases/CookiesDatabase.h @@ -33,9 +33,11 @@ public: // The public functions. static void addDatabase(); static void addCookie(const QNetworkCookie &cookie); + static int cookieCount(); static void deleteAllCookies(); static void deleteCookie(const QNetworkCookie &cookie); static QList* getCookies(); + static QNetworkCookie* getCookieById(const int &id); static bool isDurable(const QNetworkCookie &cookie); static bool isUpdate(const QNetworkCookie &cookie); static void updateCookie(const QNetworkCookie &cookie); diff --git a/src/delegates/CMakeLists.txt b/src/delegates/CMakeLists.txt new file mode 100644 index 0000000..d56c050 --- /dev/null +++ b/src/delegates/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright © 2022 Soren Stoutner . +# +# This file is part of 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 . + + +# List the sources to include in the executable. +target_sources(privacy-browser PRIVATE + ViewOnlyDelegate.cpp +) diff --git a/src/delegates/ViewOnlyDelegate.cpp b/src/delegates/ViewOnlyDelegate.cpp new file mode 100644 index 0000000..ab7f873 --- /dev/null +++ b/src/delegates/ViewOnlyDelegate.cpp @@ -0,0 +1,34 @@ + /* + * Copyright © 2022 Soren Stoutner . + * + * This file is part of 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 . + */ + +// Application headers. +#include "ViewOnlyDelegate.h" + +ViewOnlyDelegate::ViewOnlyDelegate(QObject *parentPointer) : QStyledItemDelegate(parentPointer) {} + +QWidget* ViewOnlyDelegate::createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionsViewItem, const QModelIndex &modelIndex) const +{ + // Instruct the compiler to ignore the unused variables. + (void) parentWidgetPointer; + (void) styleOptionsViewItem; + (void) modelIndex; + + // Disable editing. + return nullptr; +} diff --git a/src/delegates/ViewOnlyDelegate.h b/src/delegates/ViewOnlyDelegate.h new file mode 100644 index 0000000..774335c --- /dev/null +++ b/src/delegates/ViewOnlyDelegate.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2022 Soren Stoutner . + * + * This file is part of 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 . + */ + +#ifndef VIEWONLYDELEGATE_H +#define VIEWONLYDELEGATE_H + +// Qt toolkit headers. +#include + +class ViewOnlyDelegate : public QStyledItemDelegate +{ + // Include the Q_OBJECT macro. + Q_OBJECT + +public: + // The default constructor. + explicit ViewOnlyDelegate(QObject *parentPointer = nullptr); + + // The public functions. + QWidget* createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionsViewItem, const QModelIndex &modelIndex) const override; +}; +#endif diff --git a/src/dialogs/CMakeLists.txt b/src/dialogs/CMakeLists.txt index 55f66fd..2b722cc 100644 --- a/src/dialogs/CMakeLists.txt +++ b/src/dialogs/CMakeLists.txt @@ -21,4 +21,5 @@ target_sources(privacy-browser PRIVATE AddOrEditCookieDialog.cpp CookiesDialog.cpp DomainSettingsDialog.cpp + DurableCookiesDialog.cpp ) diff --git a/src/dialogs/CookiesDialog.cpp b/src/dialogs/CookiesDialog.cpp index fa9679c..612888d 100644 --- a/src/dialogs/CookiesDialog.cpp +++ b/src/dialogs/CookiesDialog.cpp @@ -20,6 +20,7 @@ // Application headers. #include "AddOrEditCookieDialog.h" #include "CookiesDialog.h" +#include "DurableCookiesDialog.h" #include "ui_CookiesDialog.h" #include "databases/CookiesDatabase.h" @@ -32,7 +33,7 @@ #include #include -// Construct the class. +// Define the cookie sort predicate. bool cookieSortPredicate(const QNetworkCookie &leftHandCookie, const QNetworkCookie &rightHandCookie) { // Check to see if the domains are identical. @@ -97,10 +98,10 @@ bool cookieSortPredicate(const QNetworkCookie &leftHandCookie, const QNetworkCoo // Sort the cookies by the top level domain. return (leftHandTopLevelDomain < rightHandTopLevelDomain); } - } } +// Construct the class. CookiesDialog::CookiesDialog(std::list *originalCookieListPointer) : QDialog(nullptr), cookieListPointer(originalCookieListPointer) { // Set the dialog window title. @@ -217,7 +218,7 @@ CookiesDialog::CookiesDialog(std::list *originalCookieListPointe // Indicate that all the rows are the same height, wich improves performance. treeViewPointer->setUniformRowHeights(true); - // Disable editing. + // Disable editing in the tree view. treeViewPointer->setEditTriggers(QAbstractItemView::NoEditTriggers); // Set the tree model. @@ -233,23 +234,26 @@ CookiesDialog::CookiesDialog(std::list *originalCookieListPointe addCookieButtonPointer = cookiesDialogUi.addCookieButton; editCookieButtonPointer = cookiesDialogUi.editCookieButton; deleteCookieButtonPointer = cookiesDialogUi.deleteCookieButton; + deleteAllButtonPointer = cookiesDialogUi.deleteAllCookiesButton; QDialogButtonBox *dialogButtonBoxPointer = cookiesDialogUi.dialogButtonBox; QPushButton *closeButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Close); - // Add a delete all button to the dialog button box. - deleteAllButtonPointer = dialogButtonBoxPointer->addButton(i18nc("Delete all cookies button", "Delete all"), QDialogButtonBox::ActionRole); + // Add buttons to the dialog button box. + durableCookiesButtonPointer = dialogButtonBoxPointer->addButton(i18nc("View the durable cookies button", "Durable cookies - %1", CookiesDatabase::cookieCount()), + QDialogButtonBox::ActionRole); - // Set the delete all button icon. - deleteAllButtonPointer->setIcon(QIcon::fromTheme("delete")); + // Set the button icons. + durableCookiesButtonPointer->setIcon(QIcon::fromTheme("view-visible")); // Connect the buttons. connect(addCookieButtonPointer, SIGNAL(clicked()), this, SLOT(showAddCookieDialog())); connect(editCookieButtonPointer, SIGNAL(clicked()), this, SLOT(showEditCookieDialog())); connect(deleteCookieButtonPointer, SIGNAL(clicked()), this, SLOT(showDeleteCookieMessageBox())); + connect(durableCookiesButtonPointer, SIGNAL(clicked()), this, SLOT(showDurableCookiesDialog())); connect(deleteAllButtonPointer, SIGNAL(clicked()), this, SLOT(showDeleteAllMessageBox())); connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject())); - // Set the cancel button to be the default. + // Set the close button to be the default. closeButtonPointer->setDefault(true); // Create the keyboard shortcuts. @@ -484,6 +488,48 @@ void CookiesDialog::deleteDomain(const QModelIndex &modelIndex, const bool &dele treeModelPointer->removeRow(modelIndex.row(), parentIndex); } +void CookiesDialog::deleteCookieFromDatabase(const QNetworkCookie &cookie) const +{ + // Get a list of the matching domains. There should only be one item in this list + QList domainList = treeModelPointer->findItems(cookie.domain()); + + // Find any matching cookies. + for (QStandardItem *domainItemPointer : domainList) + { + // Get the number of cookies in the domain. + int numberOfCookies = domainItemPointer->rowCount(); + + // Initialize the tracking variables. + bool cookieFound = false; + int currentRow = 0; + + // Find the cookie in the tree model. + while (!cookieFound && (currentRow < numberOfCookies)) + { + // Get the name item. + QStandardItem *nameItemPointer = domainItemPointer->child(currentRow); + + // Get the name model index. + QModelIndex nameModelIndex = nameItemPointer->index(); + + // Check to see if the name and the path match. + if ((nameModelIndex.data().toString() == cookie.name()) && (nameModelIndex.siblingAtColumn(2).data().toString() == cookie.path())) + { + // Set the current index. + treeSelectionModelPointer->setCurrentIndex(nameModelIndex, QItemSelectionModel::ClearAndSelect); + + // Delete the cookie. + deleteCookieFromDialog(cookie); + + // Mark the cookie as found. + cookieFound = true; + } + + // Move to the next row. + ++currentRow; + } + } +} void CookiesDialog::deleteCookieFromDialog(const QNetworkCookie &cookie) const { @@ -654,6 +700,20 @@ void CookiesDialog::showDeleteCookieMessageBox() const } } +void CookiesDialog::showDurableCookiesDialog() const +{ + // Instantiate a durable cookies dialog. + QDialog *durableCookiesDialogPointer = new DurableCookiesDialog(); + + // Show the dialog. + durableCookiesDialogPointer->show(); + + // Process cookie changes. + connect(durableCookiesDialogPointer, SIGNAL(addingCookie(QNetworkCookie, bool)), this, SLOT(addCookieFromDialog(QNetworkCookie, bool))); + connect(durableCookiesDialogPointer, SIGNAL(deletingCookie(QNetworkCookie)), this, SLOT(deleteCookieFromDatabase(QNetworkCookie))); + connect(durableCookiesDialogPointer, SIGNAL(updateParentUi()), this, SLOT(updateUi())); +} + void CookiesDialog::showEditCookieDialog() const { // Get the current model index. @@ -718,4 +778,7 @@ void CookiesDialog::updateUi() const // Reset the button text. deleteCookieButtonPointer->setText(i18nc("Delete cookie button.", "&Delete cookie")); } + + // Update the text of the durable cookies button. + durableCookiesButtonPointer->setText(i18nc("View the durable cookies button", "Durable cookies - %1", CookiesDatabase::cookieCount())); } diff --git a/src/dialogs/CookiesDialog.h b/src/dialogs/CookiesDialog.h index 89c2be4..36a7d72 100644 --- a/src/dialogs/CookiesDialog.h +++ b/src/dialogs/CookiesDialog.h @@ -48,10 +48,12 @@ signals: private Q_SLOTS: // The private slots. void addCookieFromDialog(const QNetworkCookie &cookie, const bool &isDurable) const; + void deleteCookieFromDatabase(const QNetworkCookie &cookie) const; void deleteCookieFromDialog(const QNetworkCookie &cookie) const; void showAddCookieDialog() const; void showDeleteAllMessageBox() const; void showDeleteCookieMessageBox() const; + void showDurableCookiesDialog() const; void showEditCookieDialog() const; void updateUi() const; @@ -61,6 +63,7 @@ private: std::list *cookieListPointer; QPushButton *deleteAllButtonPointer; QPushButton *deleteCookieButtonPointer; + QPushButton *durableCookiesButtonPointer; QPushButton *editCookieButtonPointer; QStandardItemModel *treeModelPointer; QItemSelectionModel *treeSelectionModelPointer; diff --git a/src/dialogs/DomainSettingsDialog.cpp b/src/dialogs/DomainSettingsDialog.cpp index 76477ec..c8dc3ea 100644 --- a/src/dialogs/DomainSettingsDialog.cpp +++ b/src/dialogs/DomainSettingsDialog.cpp @@ -561,12 +561,12 @@ void DomainSettingsDialog::updateUi() const // Update the delete button status. deleteDomainButtonPointer->setEnabled(domainsSelectionModelPointer->hasSelection()); - // Update the apply button status. - applyButtonPointer->setEnabled(domainsTableModelPointer->isDirty()); - // Update the reset button status. resetButtonPointer->setEnabled(domainsTableModelPointer->isDirty()); + // Update the apply button status. + applyButtonPointer->setEnabled(domainsTableModelPointer->isDirty()); + // Display the domain settings if there is at least one domain. domainSettingsWidgetPointer->setVisible(domainsTableModelPointer->rowCount() > 0); } diff --git a/src/dialogs/DurableCookiesDialog.cpp b/src/dialogs/DurableCookiesDialog.cpp new file mode 100644 index 0000000..d998c20 --- /dev/null +++ b/src/dialogs/DurableCookiesDialog.cpp @@ -0,0 +1,239 @@ +/* + * Copyright © 2022 Soren Stoutner . + * + * This file is part of 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 . + */ + +// Application headers. +#include "DurableCookiesDialog.h" +#include "ui_DurableCookiesDialog.h" +#include "databases/CookiesDatabase.h" +#include "delegates/ViewOnlyDelegate.h" + +// KDE Frameworks headers. +#include + +DurableCookiesDialog::DurableCookiesDialog() : QDialog(nullptr) +{ + // Set the dialog window title. + setWindowTitle(i18nc("The durable cookies dialog window title", "Durable Cookies")); + + // Set the window modality. + setWindowModality(Qt::WindowModality::ApplicationModal); + + // Instantiate the durable cookies dialog UI. + Ui::DurableCookiesDialog durableCookiesDialogUi; + + // Setup the UI. + durableCookiesDialogUi.setupUi(this); + + // Get a handle for the table view. + QTableView *tableViewPointer = durableCookiesDialogUi.tableView; + + // Create the durable cookies table model. + durableCookiesTableModelPointer = new QSqlTableModel(nullptr, QSqlDatabase::database(CookiesDatabase::CONNECTION_NAME)); + + // Set the table. + durableCookiesTableModelPointer->setTable(CookiesDatabase::COOKIES_TABLE); + + // Set the edit strategy. + durableCookiesTableModelPointer->setEditStrategy(QSqlTableModel::OnManualSubmit); + + // Populate the model. + durableCookiesTableModelPointer->select(); + + // Set the model. + tableViewPointer->setModel(durableCookiesTableModelPointer); + + // Instantiate the view only delegate. + ViewOnlyDelegate *viewOnlyDelegatePointer = new ViewOnlyDelegate(); + + // Disable editing the first column. + tableViewPointer->setItemDelegateForColumn(0, viewOnlyDelegatePointer); + + // Optimize the width of the columns. + tableViewPointer->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + + // Get the seleciton model. + tableSelectionModelPointer = tableViewPointer->selectionModel(); + + // Update the UI when the selection changes. + connect(tableSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi())); + + // Update the UI when the table model data changes. + connect(durableCookiesTableModelPointer, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(updateUi())); + + // Get handles for the buttons. + QPushButton *addCookieButtonPointer = durableCookiesDialogUi.addCookieButton; + deleteCookieButtonPointer = durableCookiesDialogUi.deleteCookieButton; + deleteAllCookiesButtonPointer = durableCookiesDialogUi.deleteAllCookiesButton; + QDialogButtonBox *dialogButtonBoxPointer = durableCookiesDialogUi.dialogButtonBox; + resetButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Reset); + applyButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Apply); + QPushButton *okButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Ok); + + // Set the OK button to be the default. + okButtonPointer->setDefault(true); + + // Connect the buttons. + connect(addCookieButtonPointer, SIGNAL(clicked()), this, SLOT(addCookie())); + connect(deleteCookieButtonPointer, SIGNAL(clicked()), this, SLOT(deleteCookie())); + connect(deleteAllCookiesButtonPointer, SIGNAL(clicked()), this, SLOT(deleteAllCookies())); + connect(resetButtonPointer, SIGNAL(clicked()), this, SLOT(reset())); + connect(dialogButtonBoxPointer, SIGNAL(accepted()), this, SLOT(ok())); + connect(applyButtonPointer, SIGNAL(clicked()), this, SLOT(apply())); + connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject())); + + // Connect the table model signals. + connect(durableCookiesTableModelPointer, SIGNAL(beforeDelete(int)), this, SLOT(beforeDelete(int))); + connect(durableCookiesTableModelPointer, SIGNAL(beforeUpdate(int, QSqlRecord &)), this, SLOT(beforeUpdate(int, QSqlRecord &))); + connect(durableCookiesTableModelPointer, SIGNAL(beforeInsert(QSqlRecord &)), this, SLOT(newCookie(QSqlRecord &))); + + // Update the UI. + updateUi(); +} + +void DurableCookiesDialog::addCookie() const +{ + // Add a new row to the bottom of the table. + durableCookiesTableModelPointer->insertRow(durableCookiesTableModelPointer->rowCount()); + + // Update the UI. + updateUi(); +} + +void DurableCookiesDialog::apply() const +{ + // Submit all pending changes. + durableCookiesTableModelPointer->submitAll(); + + // Update the UI. + updateUi(); +} + +void DurableCookiesDialog::beforeDelete(int row) const +{ + // Get the SQL record for the row to be deleted. + QSqlRecord sqlRecord = durableCookiesTableModelPointer->record(row); + + // Create a network cookie. + QNetworkCookie cookie; + + // Populate the network cookie. + cookie.setDomain(sqlRecord.value(CookiesDatabase::DOMAIN).toString()); + cookie.setName(sqlRecord.value(CookiesDatabase::NAME).toByteArray()); + cookie.setPath(sqlRecord.value(CookiesDatabase::PATH).toString()); + + // Delete the cookie. + emit deletingCookie(cookie); +} + +void DurableCookiesDialog::beforeUpdate(int row, QSqlRecord &sqlRecord) const +{ + // Tell the compiler to ignore the unused row parameter. + (void) row; + + // Delete the old cookie if the core attributes are changing. + if (sqlRecord.isGenerated(CookiesDatabase::DOMAIN) || sqlRecord.isGenerated(CookiesDatabase::NAME) || sqlRecord.isGenerated(CookiesDatabase::PATH)) + { + // Get the ID of the cookie + int id = sqlRecord.value(CookiesDatabase::_ID).toInt(); + + // Get the cookie. + QNetworkCookie *cookiePointer = CookiesDatabase::getCookieById(id); + + // Delete the cookie. + emit deletingCookie(*cookiePointer); + } + + // Add the new cookie, which modifies any existing cookies with the same core attributes. + newCookie(sqlRecord); +} + +void DurableCookiesDialog::deleteAllCookies() const +{ + // Mark all the cookies for deletion. + durableCookiesTableModelPointer->removeRows(0, durableCookiesTableModelPointer->rowCount()); + + // Update the UI. + updateUi(); +} + +void DurableCookiesDialog::deleteCookie() const +{ + // Delete the currently selected row. + durableCookiesTableModelPointer->removeRow(tableSelectionModelPointer->selectedRows()[0].row()); + + // Update the UI. + updateUi(); +} + +void DurableCookiesDialog::newCookie(QSqlRecord &sqlRecord) const +{ + // Create a network cookie. + QNetworkCookie cookie; + + // Populate the network cookie from the SQL record. + cookie.setDomain(sqlRecord.value(CookiesDatabase::DOMAIN).toString()); + cookie.setName(sqlRecord.value(CookiesDatabase::NAME).toByteArray()); + cookie.setPath(sqlRecord.value(CookiesDatabase::PATH).toString()); + cookie.setExpirationDate(QDateTime::fromString(sqlRecord.value(CookiesDatabase::EXPIRATION_DATE).toString(), Qt::ISODate)); + cookie.setHttpOnly(sqlRecord.value(CookiesDatabase::HTTP_ONLY).toBool()); + cookie.setSecure(sqlRecord.value(CookiesDatabase::SECURE).toBool()); + cookie.setValue(sqlRecord.value(CookiesDatabase::VALUE).toByteArray()); + + // Update the cookie in the cookies dialog tree, cookies list, and cookie store. + emit addingCookie(cookie, false); +} + +void DurableCookiesDialog::ok() +{ + // Submit all pending changes. + durableCookiesTableModelPointer->submitAll(); + + // Update the parent UI. + updateParentUi(); + + // Close the dialog. + accept(); +} + +void DurableCookiesDialog::reset() const +{ + // Cancel all pending changes. + durableCookiesTableModelPointer->revertAll(); + + // Update the UI. + updateUi(); +} + +void DurableCookiesDialog::updateUi() const +{ + // Update the delete button status. + deleteCookieButtonPointer->setEnabled(tableSelectionModelPointer->hasSelection()); + + // Update the delete all button status. + deleteAllCookiesButtonPointer->setEnabled(durableCookiesTableModelPointer->rowCount() > 0); + + // Update the reset button status. + resetButtonPointer->setEnabled(durableCookiesTableModelPointer->isDirty()); + + // Update the apply button status. + applyButtonPointer->setEnabled(durableCookiesTableModelPointer->isDirty()); + + // Update the parent UI. + emit updateParentUi(); +} diff --git a/src/dialogs/DurableCookiesDialog.h b/src/dialogs/DurableCookiesDialog.h new file mode 100644 index 0000000..61ffe5f --- /dev/null +++ b/src/dialogs/DurableCookiesDialog.h @@ -0,0 +1,66 @@ +/* + * Copyright © 2022 Soren Stoutner . + * + * This file is part of 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 . + */ + +#ifndef DURABLECOOKIESDIALOG_H +#define DURABLECOOKIESDIALOG_H + +// Qt toolkit headers. +#include +#include +#include +#include + +class DurableCookiesDialog : public QDialog +{ + // Include the Q_OBJECT macro. + Q_OBJECT + +public: + // The default constructor. + explicit DurableCookiesDialog(); + +signals: + // The signals. + void addingCookie(const QNetworkCookie &cookie, const bool &addToDatabase) const; + void deletingCookie(const QNetworkCookie &cookie) const; + void updateParentUi() const; + +private Q_SLOTS: + // The private slots. + void addCookie() const; + void apply() const; + void beforeDelete(int row) const; + void beforeUpdate(int row, QSqlRecord &sqlRecord) const; + void deleteAllCookies() const; + void deleteCookie() const; + void newCookie(QSqlRecord &sqlRecord) const; + void ok(); + void reset() const; + void updateUi() const; + +private: + // The private variables. + QPushButton *applyButtonPointer; + QPushButton *deleteAllCookiesButtonPointer; + QPushButton *deleteCookieButtonPointer; + QSqlTableModel *durableCookiesTableModelPointer; + QItemSelectionModel *tableSelectionModelPointer; + QPushButton *resetButtonPointer; +}; +#endif diff --git a/src/filters/MouseEventFilter.cpp b/src/filters/MouseEventFilter.cpp index b6cb81f..1d08396 100644 --- a/src/filters/MouseEventFilter.cpp +++ b/src/filters/MouseEventFilter.cpp @@ -34,7 +34,7 @@ bool MouseEventFilter::eventFilter(QObject *objectPointer, QEvent *eventPointer) if (eventPointer->type() == QEvent::MouseButtonPress) { // Tell the compiler to ignore the unused object pointer. - (void)objectPointer; + (void) objectPointer; // Cast the event to a mouse event. QMouseEvent *mouseEventPointer = static_cast(eventPointer); diff --git a/src/uis/CookiesDialog.ui b/src/uis/CookiesDialog.ui index 9c3c2dc..d182c03 100644 --- a/src/uis/CookiesDialog.ui +++ b/src/uis/CookiesDialog.ui @@ -33,11 +33,12 @@ + - + @@ -66,11 +67,11 @@ - + - De&lete cookie + &Delete cookie @@ -79,7 +80,20 @@ - + + + + + Delete &all + + + + + + + + + diff --git a/src/uis/DurableCookiesDialog.ui b/src/uis/DurableCookiesDialog.ui new file mode 100644 index 0000000..d1ee522 --- /dev/null +++ b/src/uis/DurableCookiesDialog.ui @@ -0,0 +1,111 @@ + + + + + + DurableCookiesDialog + + + + + 0 + 0 + 900 + 1400 + + + + + + + + + QAbstractItemView::SingleSelection + + + + QAbstractItemView::SelectRows + + + + + + + + + + + + &Add cookie + + + + + + + + + + + + + &Delete cookie + + + + + + + + + + + + + Delete &all + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + QDialogButtonBox::Reset | QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel + + + + + + + +