2 * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
6 * Privacy Browser PC is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser PC is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser PC. If not, see <http://www.gnu.org/licenses/>.
20 // Application headers.
21 #include "AddOrEditCookieDialog.h"
22 #include "CookiesDialog.h"
23 #include "ui_CookiesDialog.h"
25 // KDE Frameworks headers.
26 #include <KLocalizedString>
28 // Qt toolkit headers.
30 #include <QMessageBox>
34 // Construct the class.
35 bool cookieSortPredicate(const QNetworkCookie &leftHandCookie, const QNetworkCookie &rightHandCookie)
37 // Check to see if the domains are identical.
38 if (leftHandCookie.domain() == rightHandCookie.domain())
40 // Check to see if the names are identical.
41 if (leftHandCookie.name() == rightHandCookie.name())
43 // Sort the cookies by the path.
44 return (leftHandCookie.path() < rightHandCookie.path());
46 else // The name are not identical.
48 // Sort the cookies by the name.
49 return (leftHandCookie.name() < rightHandCookie.name());
52 else // The domains are not identical.
54 // Get copies of the domains.
55 QString leftHandDomain = leftHandCookie.domain();
56 QString rightHandDomain = rightHandCookie.domain();
58 // Get the top level domains.
59 QString leftHandTopLevelDomain = leftHandDomain.section('.', -1);
60 QString rightHandTopLevelDomain = rightHandDomain.section('.', -1);
62 // Get the second level domains.
63 QString leftHandSecondLevelDomain = leftHandDomain.section('.', -2);
64 QString rightHandSecondLevelDomain = rightHandDomain.section('.', -2);
66 // Get the third level domains.
67 QString leftHandThirdLevelDomain = leftHandDomain.section('.', -3);
68 QString rightHandThirdLevelDomain = rightHandDomain.section('.', -3);
70 // Check to see if the top level domains are the same.
71 if (leftHandTopLevelDomain == rightHandTopLevelDomain)
73 // Check to see if the second level domains are the same.
74 if (leftHandSecondLevelDomain == rightHandSecondLevelDomain)
76 // Check to see if the third level domains are the same.
77 if (leftHandThirdLevelDomain == rightHandThirdLevelDomain)
79 // Sort the cookies by the full domain because they share the same third level domain.
80 return (leftHandDomain < rightHandDomain);
82 else // The second level domains are the same, but the third level domains are different.
84 // Sort the cookies by the third level domains.
85 return (leftHandThirdLevelDomain < rightHandThirdLevelDomain);
88 else // The top level domains are the same, but the second level domains are diferent.
90 // Sort the cookies by the second level domain.
91 return (leftHandSecondLevelDomain < rightHandSecondLevelDomain);
94 else // The top level domains are different.
96 // Sort the cookies by the top level domain.
97 return (leftHandTopLevelDomain < rightHandTopLevelDomain);
103 CookiesDialog::CookiesDialog(std::list<QNetworkCookie> *originalCookieListPointer) : QDialog(nullptr), cookieListPointer(originalCookieListPointer)
105 // Set the dialog window title.
106 setWindowTitle(i18nc("The cookies dialog window title", "Cookies"));
108 // Set the window modality.
109 setWindowModality(Qt::WindowModality::ApplicationModal);
111 // Instantiate the cookie settings dialog UI.
112 Ui::CookiesDialog cookiesDialogUi;
115 cookiesDialogUi.setupUi(this);
117 // Get a handle for the tree view.
118 treeViewPointer = cookiesDialogUi.treeView;
120 // Initialize the standard item model.
121 standardItemModelPointer = new QStandardItemModel();
123 // Set the column count.
124 standardItemModelPointer->setColumnCount(6);
126 // Set the header data.
127 standardItemModelPointer->setHeaderData(0, Qt::Horizontal, i18nc("The cookie Name header.", "Name"));
128 standardItemModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The cookie Path header.", "Path"));
129 standardItemModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The cookie Expiration Date header.", "Expiration Date"));
130 standardItemModelPointer->setHeaderData(3, Qt::Horizontal, i18nc("The cookie HTTP Only header.", "HTTP Only"));
131 standardItemModelPointer->setHeaderData(4, Qt::Horizontal, i18nc("The cookie Secure header.", "Secure"));
132 standardItemModelPointer->setHeaderData(5, Qt::Horizontal, i18nc("The cookie Value header.", "Value"));
134 // Set the header tool tips.
135 standardItemModelPointer->horizontalHeaderItem(0)->setToolTip(i18nc("The cookie Name tool tip.",
136 "The name identifies the cookie. Each cookie has a unique combination of domain, name, and path."));
137 standardItemModelPointer->horizontalHeaderItem(1)->setToolTip(i18nc("The cookie Path tool tip.", "Websites can restrict cookie access to subpath of their URL."));
138 standardItemModelPointer->horizontalHeaderItem(2)->setToolTip(i18nc("The cookie Expiration Date tool tip.",
139 "Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes."));
140 standardItemModelPointer->horizontalHeaderItem(3)->setToolTip(i18nc("The cookie HTTP Only tool tip.",
141 "Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks."));
142 standardItemModelPointer->horizontalHeaderItem(4)->setToolTip(i18nc("The cookie Secure tool tip.", "Only allow the cookie to be transferred across HTTPS (as opposed to HTTP)."));
143 standardItemModelPointer->horizontalHeaderItem(5)->setToolTip(i18nc("The cookie Value tool tip.", "The value contains the cookie data."));
145 // Sort the cookie list.
146 cookieListPointer->sort(cookieSortPredicate);
148 // Create the current domain string.
149 QString currentDomainString = "";
151 // Create the current domain standard item pointer.
152 QStandardItem *currentDomainStandardItemPointer;
154 // Populate the VBoxLayout.
155 for (QNetworkCookie cookie : *cookieListPointer)
157 // Get the cookie domain.
158 QString cookieDomain = cookie.domain();
160 // Check to see if the cookie is a member of the current domain.
161 if (cookieDomain != currentDomainString) // Create a new domain in the tree.
163 // Create a list for the domain standard items.
164 QList<QStandardItem*> domainStandardItemList;
166 // Create the new domain standard items.
167 QStandardItem *domainStandardItemPointer = new QStandardItem(cookieDomain);
168 QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral(""));
169 QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral(""));
170 QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral(""));
171 QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral(""));
172 QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral(""));
174 // Disable editing of the domain.
175 domainStandardItemPointer->setEditable(false);
176 pathStandardItemPointer->setEditable(false);
177 expirationDateStandardItemPointer->setEditable(false);
178 isHttpOnlyStandardItemPointer->setEditable(false);
179 isSecureStandardItemPointer->setEditable(false);
180 valueStandardItemPointer->setEditable(false);
182 // Populate the domain standard item list.
183 domainStandardItemList.append(domainStandardItemPointer);
184 domainStandardItemList.append(pathStandardItemPointer);
185 domainStandardItemList.append(expirationDateStandardItemPointer);
186 domainStandardItemList.append(isHttpOnlyStandardItemPointer);
187 domainStandardItemList.append(isSecureStandardItemPointer);
188 domainStandardItemList.append(valueStandardItemPointer);
190 // Add the domain to the tree.
191 standardItemModelPointer->invisibleRootItem()->appendRow(domainStandardItemList);
193 // Update the current domain string.
194 currentDomainString = cookieDomain;
196 // Update the current domain standard item pointer.
197 currentDomainStandardItemPointer = domainStandardItemPointer;
200 // Create a list for the cookie standard items.
201 QList<QStandardItem*> cookieStandardItemList;
203 // Create the cookie standard items.
204 QStandardItem *nameStandardItemPointer = new QStandardItem(QString(cookie.name()));
205 QStandardItem *pathStandardItemPointer = new QStandardItem(QString(cookie.path()));
206 QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
207 QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
208 QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
209 QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value()));
211 // Disable editing of the cookie standard items.
212 nameStandardItemPointer->setEditable(false);
213 pathStandardItemPointer->setEditable(false);
214 expirationDateStandardItemPointer->setEditable(false);
215 isHttpOnlyStandardItemPointer->setEditable(false);
216 isSecureStandardItemPointer->setEditable(false);
217 valueStandardItemPointer->setEditable(false);
219 // Populate the cookie standard item list.
220 cookieStandardItemList.append(nameStandardItemPointer);
221 cookieStandardItemList.append(pathStandardItemPointer);
222 cookieStandardItemList.append(expirationDateStandardItemPointer);
223 cookieStandardItemList.append(isHttpOnlyStandardItemPointer);
224 cookieStandardItemList.append(isSecureStandardItemPointer);
225 cookieStandardItemList.append(valueStandardItemPointer);
227 // Add the cookie to the tree.
228 currentDomainStandardItemPointer->appendRow(cookieStandardItemList);
231 // Auto resize the headers.
232 treeViewPointer->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
234 // Disable stretching the last section. Otherwise, the Value field will be truncated to the width of the window when a row is expanded.
235 treeViewPointer->header()->setStretchLastSection(false);
237 // Don't elide the Value field (or any other field).
238 treeViewPointer->setTextElideMode(Qt::ElideNone);
240 // Indicate that all the rows are the same height, wich improves performance.
241 treeViewPointer->setUniformRowHeights(true);
243 // Set the tree view model.
244 treeViewPointer->setModel(standardItemModelPointer);
246 // Get a handle for the tree view selection model.
247 treeViewSelectionModelPointer = treeViewPointer->selectionModel();
249 // Listen for selection changes.
250 connect(treeViewSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi()));
252 // Get handles for the buttons.
253 addCookieButtonPointer = cookiesDialogUi.addCookieButton;
254 editCookieButtonPointer = cookiesDialogUi.editCookieButton;
255 deleteCookieButtonPointer = cookiesDialogUi.deleteCookieButton;
256 QDialogButtonBox *dialogButtonBoxPointer = cookiesDialogUi.dialogButtonBox;
257 QPushButton *closeButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Close);
259 // Add a delete all button to the dialog button box.
260 deleteAllButtonPointer = dialogButtonBoxPointer->addButton(i18nc("Delete all cookies button", "Delete all"), QDialogButtonBox::ActionRole);
262 // Set the delete all button icon.
263 deleteAllButtonPointer->setIcon(QIcon::fromTheme("delete"));
265 // Connect the buttons.
266 connect(addCookieButtonPointer, SIGNAL(clicked()), this, SLOT(showAddCookieDialog()));
267 connect(editCookieButtonPointer, SIGNAL(clicked()), this, SLOT(showEditCookieDialog()));
268 connect(deleteCookieButtonPointer, SIGNAL(clicked()), this, SLOT(showDeleteCookieMessageBox()));
269 connect(deleteAllButtonPointer, SIGNAL(clicked()), this, SLOT(showDeleteAllMessageBox()));
270 connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
272 // Set the cancel button to be the default.
273 closeButtonPointer->setDefault(true);
275 // Create the keyboard shortcuts.
276 QShortcut *aShortcutPointer = new QShortcut(QKeySequence(i18nc("The add cookie key shortcut.", "a")), this);
277 QShortcut *eShortcutPointer = new QShortcut(QKeySequence(i18nc("The edit cookie key shorcut.", "e")), this);
278 QShortcut *dShortcutPointer = new QShortcut(QKeySequence(i18nc("The delete cookie key shortcut.", "d")), this);
279 QShortcut *deleteShortcutPointer = new QShortcut(QKeySequence::Delete, this);
280 QShortcut *lShortcutPointer = new QShortcut(QKeySequence(i18nc("The delete all key shortcut.", "l")), this);
281 QShortcut *cShortcutPointer = new QShortcut(QKeySequence(i18nc("The close key shortcut.", "c")), this);
282 QShortcut *quitShortcutPointer = new QShortcut(QKeySequence::Quit, this);
284 // Connect the keyboard shortcuts to the buttons.
285 connect(aShortcutPointer, SIGNAL(activated()), addCookieButtonPointer, SLOT(click()));
286 connect(eShortcutPointer, SIGNAL(activated()), editCookieButtonPointer, SLOT(click()));
287 connect(dShortcutPointer, SIGNAL(activated()), deleteCookieButtonPointer, SLOT(click()));
288 connect(deleteShortcutPointer, SIGNAL(activated()), deleteCookieButtonPointer, SLOT(click()));
289 connect(lShortcutPointer, SIGNAL(activated()), deleteAllButtonPointer, SLOT(click()));
290 connect(cShortcutPointer, SIGNAL(activated()), closeButtonPointer, SLOT(click()));
291 connect(quitShortcutPointer, SIGNAL(activated()), closeButtonPointer, SLOT(click()));
293 // Edit a cookie when it is double clicked.
294 connect(treeViewPointer, SIGNAL(doubleClicked(QModelIndex)), editCookieButtonPointer, SLOT(click()));
300 void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const
302 // Add the cookie to the cookie list and the cookie store.
303 emit addCookie(cookie);
305 // Get the new domain string.
306 QString newDomain = cookie.domain();
308 // Check to see if the domain already exists in the model.
309 QList<QStandardItem*> currentDomainStandardItemList = standardItemModelPointer->findItems(newDomain);
311 // Create a domain standard item pointer.
312 QStandardItem *domainStandardItemPointer;
314 // Prepare the domain standard item pointer.
315 if (currentDomainStandardItemList.isEmpty()) // The domain doesn't currently exist in the tree.
317 // Create a list for the domain standard items.
318 QList<QStandardItem*> domainStandardItemList;
320 // Create the new domain standard items.
321 domainStandardItemPointer = new QStandardItem(newDomain);
322 QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral(""));
323 QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral(""));
324 QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral(""));
325 QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral(""));
326 QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral(""));
328 // Disable editing of the domain.
329 domainStandardItemPointer->setEditable(false);
330 pathStandardItemPointer->setEditable(false);
331 expirationDateStandardItemPointer->setEditable(false);
332 isHttpOnlyStandardItemPointer->setEditable(false);
333 isSecureStandardItemPointer->setEditable(false);
334 valueStandardItemPointer->setEditable(false);
336 // Populate the domain standard item list.
337 domainStandardItemList.append(domainStandardItemPointer);
338 domainStandardItemList.append(pathStandardItemPointer);
339 domainStandardItemList.append(expirationDateStandardItemPointer);
340 domainStandardItemList.append(isHttpOnlyStandardItemPointer);
341 domainStandardItemList.append(isSecureStandardItemPointer);
342 domainStandardItemList.append(valueStandardItemPointer);
344 // Create the insert domain row number.
345 int insertDomainRowNumber = 0;
347 // Get the number of domains in the tree.
348 int numberOfDomains = standardItemModelPointer->invisibleRootItem()->rowCount();
350 // Get the new domain strings.
351 QString newDomainTopLevelDomain = newDomain.section('.', -1);
352 QString newDomainSecondLevelDomain = newDomain.section('.', -2);
353 QString newDomainThirdLevelDomain = newDomain.section('.', -3);
355 // Iterate through all the domains.
356 for (int i = 0; i < numberOfDomains; ++i)
358 // Get the current domain strings.
359 QString currentDomain = standardItemModelPointer->invisibleRootItem()->child(i, 0)->index().data().toString();
360 QString currentDomainTopLevelDomain = currentDomain.section('.', -1);
361 QString currentDomainSecondLevelDomain = currentDomain.section('.', -2);
362 QString currentDomainThirdLevelDomain = currentDomain.section('.', -3);
364 // Check to see if the new domain should be inserted after the current domain.
365 if (newDomainTopLevelDomain > currentDomainTopLevelDomain)
367 // Insert the new domain after the current domain.
368 insertDomainRowNumber = i + 1;
370 else if ((newDomainTopLevelDomain == currentDomainTopLevelDomain) && (newDomainSecondLevelDomain > currentDomainSecondLevelDomain))
372 // Insert the new domain after the current domain.
373 insertDomainRowNumber = i + 1;
375 else if ((newDomainSecondLevelDomain == currentDomainSecondLevelDomain) && (newDomainThirdLevelDomain > currentDomainThirdLevelDomain))
377 // Insert the new domain after the current domain.
378 insertDomainRowNumber = i + 1;
380 else if ((newDomainThirdLevelDomain == currentDomainThirdLevelDomain) && (newDomain > currentDomain))
382 // Insert the new domain after the current domain.
383 insertDomainRowNumber = i + 1;
387 // Add the domain to the tree.
388 standardItemModelPointer->invisibleRootItem()->insertRow(insertDomainRowNumber, domainStandardItemList);
390 else // The domain already exists in the tree.
392 // Use the current domain standard item.
393 domainStandardItemPointer = currentDomainStandardItemList[0];
396 // Get strings for the new cookie name and path (used later in the placement of the row).
397 QString newCookieName = QString(cookie.name());
398 QString newCookiePath = QString(cookie.path());
400 // Create a list for the cookie standard items.
401 QList<QStandardItem*> cookieStandardItemList;
403 // Create the cookie standard items.
404 QStandardItem *nameStandardItemPointer = new QStandardItem(newCookieName);
405 QStandardItem *pathStandardItemPointer = new QStandardItem(newCookiePath);
406 QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
407 QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
408 QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
409 QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value()));
411 // Disable editing of the cookie standard items.
412 nameStandardItemPointer->setEditable(false);
413 pathStandardItemPointer->setEditable(false);
414 expirationDateStandardItemPointer->setEditable(false);
415 isHttpOnlyStandardItemPointer->setEditable(false);
416 isSecureStandardItemPointer->setEditable(false);
417 valueStandardItemPointer->setEditable(false);
419 // Populate the cookie standard item list.
420 cookieStandardItemList.append(nameStandardItemPointer);
421 cookieStandardItemList.append(pathStandardItemPointer);
422 cookieStandardItemList.append(expirationDateStandardItemPointer);
423 cookieStandardItemList.append(isHttpOnlyStandardItemPointer);
424 cookieStandardItemList.append(isSecureStandardItemPointer);
425 cookieStandardItemList.append(valueStandardItemPointer);
427 // Create the insert cookie row number.
428 int insertCookieRowNumber = 0;
430 // Get the number of cookies in the domain.
431 int numberOfCookies = domainStandardItemPointer->rowCount();
433 // Iterate through the cookies for this domain.
434 for (int i = 0; i < numberOfCookies; ++i)
436 // Get the current cookie name and path at the indicated row.
437 QString currentCookieName = domainStandardItemPointer->child(i, 0)->index().data().toString();
438 QString currentCookiePath = domainStandardItemPointer->child(i, 1)->index().data().toString();
440 // Check to see if the new cookie should be inserted after the current cookie.
441 if (newCookieName > currentCookieName)
443 // Insert the new cookie after the current cookie.
444 insertCookieRowNumber = i + 1;
446 else if ((newCookieName == currentCookieName) && (newCookiePath > currentCookiePath))
448 // Insert the new cookie after the current cookie.
449 insertCookieRowNumber = i + 1;
453 // Add the cookie to the tree.
454 domainStandardItemPointer->insertRow(insertCookieRowNumber, cookieStandardItemList);
456 // Get the new cookie model index.
457 QModelIndex newCookieIndex = nameStandardItemPointer->index();
459 // Set the new cookie to be the current index.
460 treeViewPointer->setCurrentIndex(newCookieIndex);
462 // Expand the parent of the new cookie.
463 treeViewPointer->expand(newCookieIndex.parent());
466 void CookiesDialog::deleteCookie(const QModelIndex &modelIndex) const
468 // Create a partial cookie.
469 QNetworkCookie partialCookie;
471 // Populate the partial cookie from the current model index.
472 partialCookie.setDomain(modelIndex.parent().siblingAtColumn(0).data().toString());
473 partialCookie.setName(modelIndex.siblingAtColumn(0).data().toString().toUtf8());
474 partialCookie.setPath(modelIndex.siblingAtColumn(1).data().toString());
476 // Create a cookie to delete.
477 QNetworkCookie cookieToDelete;
479 // Search for the partial cookie in the cookie list.
480 for (QNetworkCookie cookie : *cookieListPointer)
482 // Store the cookie to delete if it has the same identifier as the partial cookie.
483 if (cookie.hasSameIdentifier(partialCookie))
484 cookieToDelete = cookie;
487 // Remove the cookie from the tree view.
488 standardItemModelPointer->removeRow(modelIndex.row(), modelIndex.parent());
490 // Delete the cookie from the cookie list and cookie store.
491 emit deleteCookie(cookieToDelete);
494 void CookiesDialog::deleteCookieFromDialog(const QNetworkCookie &cookie) const
496 // Get the current model index.
497 QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
499 // Get the parent index.
500 QModelIndex parentIndex = currentIndex.parent();
502 // Remove the cookie from the tree view.
503 standardItemModelPointer->removeRow(currentIndex.row(), parentIndex);
505 // Remove the domain from the tree view if its only cookie has been deleted.
506 if (standardItemModelPointer->rowCount(parentIndex) == 0)
507 standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
509 // Delete the cookie from the cookie list and cookie store.
510 emit deleteCookie(cookie);
513 void CookiesDialog::showAddCookieDialog() const
515 // Instantiate an add cookie dialog.
516 QDialog *addCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::AddCookie);
519 addCookieDialogPointer->show();
521 // Add the cookie if directed.
522 connect(addCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie)));
525 void CookiesDialog::showDeleteAllMessageBox() const
527 // Instantiate a delete all message box.
528 QMessageBox deleteAllCookiesMessageBox;
531 deleteAllCookiesMessageBox.setIcon(QMessageBox::Warning);
533 // Set the window title.
534 deleteAllCookiesMessageBox.setWindowTitle(i18nc("Delete all cookies dialog title", "Delete All Cookies"));
537 deleteAllCookiesMessageBox.setText(i18nc("Delete all cookies dialog text", "Delete all cookies?"));
539 // Set the standard buttons.
540 deleteAllCookiesMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
542 // Set the default button.
543 deleteAllCookiesMessageBox.setDefaultButton(QMessageBox::No);
545 // Display the dialog and capture the return value.
546 int returnValue = deleteAllCookiesMessageBox.exec();
548 // Delete all cookies if instructed.
549 if (returnValue == QMessageBox::Yes)
551 // Delete all the cookies.
552 emit deleteAllCookies();
554 // Clear the standard item model.
555 standardItemModelPointer->clear();
562 void CookiesDialog::showDeleteCookieMessageBox() const
564 // Get the current model index.
565 QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
567 // Get the parent model index.
568 QModelIndex parentIndex = currentIndex.parent();
570 // Determine if a domain is selected.
571 bool isDomain = standardItemModelPointer->hasChildren(currentIndex);
573 // Instantiate a delete cookie message box.
574 QMessageBox deleteCookieMessageBox;
577 deleteCookieMessageBox.setIcon(QMessageBox::Warning);
581 // Get the number of cookies.
582 int numberOfCookiesToDelete = standardItemModelPointer->rowCount(currentIndex);
584 // Set the window title.
585 deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookies dialog title", "Delete %1 Cookies", numberOfCookiesToDelete));
588 deleteCookieMessageBox.setText(i18nc("Delete cookies dialog text", "Delete %1 cookies?", numberOfCookiesToDelete));
592 // Set the window title.
593 deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookie dialog title", "Delete 1 Cookie"));
596 deleteCookieMessageBox.setText(i18nc("Delete cookie dialog text", "Delete 1 cookie?"));
599 // Set the standard buttons.
600 deleteCookieMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
602 // Set the default button.
603 deleteCookieMessageBox.setDefaultButton(QMessageBox::No);
605 // Display the dialog and capture the return value.
606 int returnValue = deleteCookieMessageBox.exec();
608 // Delete the cookie if instructed.
609 if (returnValue == QMessageBox::Yes)
611 // Delete the cookies according to the selection.
612 if (isDomain) // A domain is selected.
614 // Get the number of cookies.
615 int numberOfCookies = standardItemModelPointer->rowCount(currentIndex);
617 // Delete each child cookie.
618 for (int i = 0; i < numberOfCookies; ++i)
620 // Delete the cookie for the first child. Once this is deleted, the second child will become the first child.
621 deleteCookie(standardItemModelPointer->index(0, 0, currentIndex));
624 // Delete the domain from the tree view.
625 standardItemModelPointer->removeRow(currentIndex.row(), parentIndex);
627 else // A single cookie is selected.
629 // Delete the cookie.
630 deleteCookie(currentIndex);
632 // Remove the domain row if its only cookie has been deleted.
633 if (standardItemModelPointer->rowCount(parentIndex) == 0)
634 standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
639 void CookiesDialog::showEditCookieDialog() const
641 // Get the current model index.
642 QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
644 // Create a partial cookie.
645 QNetworkCookie partialCookie;
647 // Populate the partial cookie from the current model index.
648 partialCookie.setDomain(currentIndex.parent().siblingAtColumn(0).data().toString());
649 partialCookie.setName(currentIndex.siblingAtColumn(0).data().toString().toUtf8());
650 partialCookie.setPath(currentIndex.siblingAtColumn(1).data().toString());
652 // Create a cookie to edit.
653 QNetworkCookie cookieToEdit;
655 // Search for the partial cookie in the cookie list.
656 for (QNetworkCookie cookie : *cookieListPointer)
658 // Store the cookie to edit if it has the same identifier as the partial cookie.
659 if (cookie.hasSameIdentifier(partialCookie))
660 cookieToEdit = cookie;
663 // Instantiate an edit cookie dialog.
664 QDialog *editCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::EditCookie, &cookieToEdit);
667 editCookieDialogPointer->show();
669 // Process cookie events.
670 connect(editCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie)));
671 connect(editCookieDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), this, SLOT(deleteCookieFromDialog(QNetworkCookie)));
674 void CookiesDialog::updateUi() const
676 // Get the current index of the first column.
677 QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex().siblingAtColumn(0);
679 // Set the status of the buttons.
680 editCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection() && !standardItemModelPointer->hasChildren(currentIndex));
681 deleteCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection());;
682 deleteAllButtonPointer->setEnabled(standardItemModelPointer->hasChildren(standardItemModelPointer->invisibleRootItem()->index()));
684 // Update the delete cookie button text.
685 if (deleteCookieButtonPointer->isEnabled()) // The button is enabled.
687 if (standardItemModelPointer->hasChildren(currentIndex)) // A domain is selected.
689 // Update the button text.
690 deleteCookieButtonPointer->setText(i18nc("Delete cookies button.", "&Delete %1 cookies", standardItemModelPointer->rowCount(currentIndex)));
692 else // A single cookie is selected.
694 // Update the button text.
695 deleteCookieButtonPointer->setText(i18nc("Delete cookies button.", "&Delete 1 cookie"));
698 else // The button is disabled.
700 // Reset the button text.
701 deleteCookieButtonPointer->setText(i18nc("Delete cookie button.", "&Delete cookie"));