]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/commitdiff
Finish block list implementation.
authorSoren Stoutner <soren@stoutner.com>
Sat, 15 Jun 2024 00:07:01 +0000 (17:07 -0700)
committerSoren Stoutner <soren@stoutner.com>
Sat, 15 Jun 2024 00:07:01 +0000 (17:07 -0700)
20 files changed:
src/CMakeLists.txt
src/delegates/CMakeLists.txt
src/delegates/ViewAndCopyDelegate.cpp [deleted file]
src/delegates/ViewAndCopyDelegate.h [deleted file]
src/dialogs/CMakeLists.txt
src/dialogs/FilterEntryDialog.cpp [new file with mode: 0644]
src/dialogs/FilterEntryDialog.h [new file with mode: 0644]
src/dialogs/FilterListsDialog.cpp
src/dialogs/FilterListsDialog.h
src/dialogs/RequestDetailDialog.cpp
src/dialogs/RequestDetailDialog.h
src/dialogs/RequestsDialog.cpp
src/helpers/FilterListHelper.cpp
src/helpers/FilterListHelper.h
src/interceptors/UrlRequestInterceptor.cpp
src/structs/EntryStruct.h
src/structs/FilterListStruct.h
src/structs/UrlStruct.h
src/uis/FilterEntryDialog.ui [new file with mode: 0644]
src/uis/RequestDetailDialog.ui

index ac2b39cbda56f9ddbd5fbeb5ac0f641a91864863..86bf0004b97f2f59f6faa724fb93a88a0f418382 100644 (file)
@@ -45,6 +45,7 @@ ki18n_wrap_ui(privacybrowser
     uis/DurableCookiesDialog.ui
     uis/EditBookmarkDialog.ui
     uis/EditFolderDialog.ui
+    uis/FilterEntryDialog.ui
     uis/FilterListsDialog.ui
     uis/HttpAuthenticationDialog.ui
     uis/RequestDetailDialog.ui
index 440ec44f5540fec1a61430956ff3e69fba816193..5e795b999653794e41503d0650c28d429975f6a9 100644 (file)
@@ -18,6 +18,5 @@
 
 # List the sources to include in the executable.
 target_sources(privacybrowser PRIVATE
-    ViewAndCopyDelegate.cpp
     ViewOnlyDelegate.cpp
 )
diff --git a/src/delegates/ViewAndCopyDelegate.cpp b/src/delegates/ViewAndCopyDelegate.cpp
deleted file mode 100644 (file)
index d3eb1f3..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
- /*
- * Copyright 2024 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 "ViewAndCopyDelegate.h"
-
-// Qt toolkit headers.
-#include <QLineEdit>
-
-ViewAndCopyDelegate::ViewAndCopyDelegate(QObject *parentObjectPointer) : QStyledItemDelegate(parentObjectPointer) {}
-
-QWidget* ViewAndCopyDelegate::createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionViewItem, const QModelIndex &modelIndex) const
-{
-    // Instruct the compiler to ignore the unused variables.
-    (void) styleOptionViewItem;
-
-    // Get the data string from the model index.
-    QString dataString = modelIndex.data().toString();
-
-    // Create a line edit.
-    QLineEdit *lineEditPointer = new QLineEdit(dataString, parentWidgetPointer);
-
-    // Set the line edit to be read only.
-    lineEditPointer->setReadOnly(true);
-
-    // Return the line edit.
-    return lineEditPointer;
-}
diff --git a/src/delegates/ViewAndCopyDelegate.h b/src/delegates/ViewAndCopyDelegate.h
deleted file mode 100644 (file)
index 722add4..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2024 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 VIEWANDCOPYDELEGATE_H
-#define VIEWANDCOPYDELEGATE_H
-
-// Qt toolkit headers.
-#include <QStyledItemDelegate>
-
-class ViewAndCopyDelegate : public QStyledItemDelegate
-{
-    // Include the Q_OBJECT macro.
-    Q_OBJECT
-
-public:
-    // The default constructor.
-    explicit ViewAndCopyDelegate(QObject *parenObjectPointer = nullptr);
-
-    // The public functions.
-    QWidget* createEditor(QWidget *parentWidgetPointer, const QStyleOptionViewItem &styleOptionViewItem, const QModelIndex &modelIndex) const override;
-};
-#endif
index 264624fc0e41ea28425751c2d0ce7453868ce33e..a0bc9eba6e3d0038d4a1170e303fd462e0a3de6f 100644 (file)
@@ -27,6 +27,7 @@ target_sources(privacybrowser PRIVATE
     DurableCookiesDialog.cpp
     EditBookmarkDialog.cpp
     EditFolderDialog.cpp
+    FilterEntryDialog.cpp
     FilterListsDialog.cpp
     HttpAuthenticationDialog.cpp
     RequestDetailDialog.cpp
diff --git a/src/dialogs/FilterEntryDialog.cpp b/src/dialogs/FilterEntryDialog.cpp
new file mode 100644 (file)
index 0000000..703ca04
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2024 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 "FilterEntryDialog.h"
+#include "GlobalVariables.h"
+#include "ui_FilterEntryDialog.h"
+
+// KDE Framework headers.
+#include <KColorScheme>
+
+// Qt toolkit headers.
+#include <QShortcut>
+
+// Construct the class.
+FilterEntryDialog::FilterEntryDialog(QWidget *parentWidgetPointer, QTableWidget *tableWidgetPointer, const int initialRow, const QString &filterListTitle, const QString &sublistTitle) :
+                                     QDialog(parentWidgetPointer), currentRow(initialRow), tableWidgetPointer(tableWidgetPointer)
+{
+    // Set the window modality.
+    setWindowModality(Qt::WindowModality::ApplicationModal);
+
+    // Instantiate the filter entry dialog UI.
+    Ui::FilterEntryDialog filterEntryDialogUi;
+
+    // Setup the UI.
+    filterEntryDialogUi.setupUi(this);
+
+    // Get handles for the views.
+    QLineEdit *filterListLineEditPointer = filterEntryDialogUi.filterListLineEdit;
+    QLineEdit *sublistLineEditPointer = filterEntryDialogUi.sublistListLineEdit;
+    appliedEntryListLineEditPointer = filterEntryDialogUi.appliedEntryListLineEdit;
+    initialMatchLineEditPointer = filterEntryDialogUi.initialMatchLineEdit;
+    finalMatchLineEditPointer = filterEntryDialogUi.finalMatchLineEdit;
+    domainLineEditPointer = filterEntryDialogUi.domainLineEdit;
+    domainListLineEditPointer = filterEntryDialogUi.domainListLineEdit;
+    thirdPartyLineEditPointer = filterEntryDialogUi.thirdPartyLineEdit;
+    hasRequestOptionsCheckBoxPointer = filterEntryDialogUi.hasRequestOptionsCheckBox;
+    fontLineEditPointer = filterEntryDialogUi.fontLineEdit;
+    imageLineEditPointer = filterEntryDialogUi.imageLineEdit;
+    mainFrameLineEditPointer = filterEntryDialogUi.mainFrameLineEdit;
+    mediaLineEditPointer = filterEntryDialogUi.mediaLineEdit;
+    objectLineEditPointer = filterEntryDialogUi.objectLineEdit;
+    otherLineEditPointer = filterEntryDialogUi.otherLineEdit;
+    pingLineEditPointer = filterEntryDialogUi.pingLineEdit;
+    scriptLineEditPointer = filterEntryDialogUi.scriptLineEdit;
+    styleSheetLineEditPointer = filterEntryDialogUi.styleSheetLineEdit;
+    subFrameLineEditPointer = filterEntryDialogUi.subFrameLineEdit;
+    xmlHttpRequestLineEditPointer = filterEntryDialogUi.xmlHttpRequestLineEdit;
+    appliedFilterOptionsLineEditPointer = filterEntryDialogUi.appliedFilterOptionsLineEdit;
+    originalFilterOptionsLineEditPointer = filterEntryDialogUi.originalFilterOptionsLineEdit;
+    originalEntryLineEditPointer = filterEntryDialogUi.originalEntryLineEdit;
+    previousButtonPointer = filterEntryDialogUi.previousButton;
+    nextButtonPointer = filterEntryDialogUi.nextButton;
+    QDialogButtonBox *dialogButtonBoxPointer = filterEntryDialogUi.dialogButtonBox;
+    QPushButton *closeButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::StandardButton::Close);
+
+    // Populate the views.
+    filterListLineEditPointer->setText(filterListTitle);
+    sublistLineEditPointer->setText(sublistTitle);
+
+    // Disable changing the checkbox checked status.
+    hasRequestOptionsCheckBoxPointer->setAttribute(Qt::WA_TransparentForMouseEvents);
+
+    // Make the close button the default.
+    closeButtonPointer->setDefault(true);
+
+    // Get the disposition line edit palettes.
+    normalBackgroundPalette = appliedEntryListLineEditPointer->palette();
+    negativeBackgroundPalette = normalBackgroundPalette;
+    positiveBackgroundPalette = normalBackgroundPalette;
+
+    // Modify the palettes.
+    KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
+    KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
+
+    // Set the sublist background palette.  TODO  Add logic for allow lists.
+    sublistLineEditPointer->setPalette(negativeBackgroundPalette);
+
+    // Set the applied entry background palette to be the same as the sublist.
+    appliedEntryListLineEditPointer->setPalette(sublistLineEditPointer->palette());
+
+    // Connect the buttons.
+    connect(previousButtonPointer, SIGNAL(clicked()), this, SLOT(previous()));
+    connect(nextButtonPointer, SIGNAL(clicked()), this, SLOT(next()));
+    connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(close()));
+
+    // Create the keyboard shortcuts.
+    QShortcut *previousShortcutPointer = new QShortcut(Qt::Key_Left, this);
+    QShortcut *nextShortcutPointer = new QShortcut(Qt::Key_Right, this);
+
+    // Connect the keyboard shortcuts to the buttons.
+    connect(previousShortcutPointer, SIGNAL(activated()), previousButtonPointer, SLOT(click()));
+    connect(nextShortcutPointer, SIGNAL(activated()), nextButtonPointer, SLOT(click()));
+
+    // Populate the dialog.
+    populateDialog(currentRow);
+}
+
+void FilterEntryDialog::populateDialog(const int row)
+{
+    // Set the window title.
+    setWindowTitle(i18nc("The filter entry dialog window title", "Filter Entry %1 Detail", row + 1));
+
+    // Select the row in the table widget (this displays the correct row highlighted in the background of the dialog).
+    tableWidgetPointer->selectRow(row);
+
+    // Determine if previous should be enabled.
+    bool previousEnabled = (row > 0);
+
+    // Determine if next should be enabled.
+    bool nextEnabled = (row < (tableWidgetPointer->rowCount() - 1));
+
+    // Populate the line edits.
+    appliedEntryListLineEditPointer->setText(tableWidgetPointer->item(row, 0)->text());
+    initialMatchLineEditPointer->setText(tableWidgetPointer->item(row, 1)->text());
+    finalMatchLineEditPointer->setText(tableWidgetPointer->item(row, 2)->text());
+    domainLineEditPointer->setText(tableWidgetPointer->item(row, 3)->text());
+    domainListLineEditPointer->setText(tableWidgetPointer->item(row, 4)->text());
+    thirdPartyLineEditPointer->setText(tableWidgetPointer->item(row, 5)->text());
+    fontLineEditPointer->setText(tableWidgetPointer->item(row, 7)->text());
+    imageLineEditPointer->setText(tableWidgetPointer->item(row, 8)->text());
+    mainFrameLineEditPointer->setText(tableWidgetPointer->item(row, 9)->text());
+    mediaLineEditPointer->setText(tableWidgetPointer->item(row, 10)->text());
+    objectLineEditPointer->setText(tableWidgetPointer->item(row, 11)->text());
+    otherLineEditPointer->setText(tableWidgetPointer->item(row, 12)->text());
+    pingLineEditPointer->setText(tableWidgetPointer->item(row, 13)->text());
+    scriptLineEditPointer->setText(tableWidgetPointer->item(row, 14)->text());
+    styleSheetLineEditPointer->setText(tableWidgetPointer->item(row, 15)->text());
+    subFrameLineEditPointer->setText(tableWidgetPointer->item(row, 16)->text());
+    xmlHttpRequestLineEditPointer->setText(tableWidgetPointer->item(row, 17)->text());
+    appliedFilterOptionsLineEditPointer->setText(tableWidgetPointer->item(row, 18)->text());
+    originalFilterOptionsLineEditPointer->setText(tableWidgetPointer->item(row, 19)->text());
+    originalEntryLineEditPointer->setText(tableWidgetPointer->item(row, 20)->text());
+
+    // Populate the check boxes.
+    hasRequestOptionsCheckBoxPointer->setChecked(tableWidgetPointer->item(row, 6)->text() == i18n("Yes"));
+
+    // Set the initial and final match background palettes.
+    setInitialAndFinalMatchBackgroundPalette(initialMatchLineEditPointer);
+    setInitialAndFinalMatchBackgroundPalette(finalMatchLineEditPointer);
+
+    // Set the request option background palettes and status.
+    setFilterOptionBackgroundPalette(domainLineEditPointer);
+    setFilterOptionBackgroundPalette(thirdPartyLineEditPointer);
+    setFilterOptionBackgroundPalette(fontLineEditPointer);
+    setFilterOptionBackgroundPalette(imageLineEditPointer);
+    setFilterOptionBackgroundPalette(mainFrameLineEditPointer);
+    setFilterOptionBackgroundPalette(mediaLineEditPointer);
+    setFilterOptionBackgroundPalette(objectLineEditPointer);
+    setFilterOptionBackgroundPalette(otherLineEditPointer);
+    setFilterOptionBackgroundPalette(pingLineEditPointer);
+    setFilterOptionBackgroundPalette(scriptLineEditPointer);
+    setFilterOptionBackgroundPalette(styleSheetLineEditPointer);
+    setFilterOptionBackgroundPalette(subFrameLineEditPointer);
+    setFilterOptionBackgroundPalette(xmlHttpRequestLineEditPointer);
+
+    // Set the request option status.
+    fontLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    imageLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    mainFrameLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    mediaLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    objectLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    otherLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    pingLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    scriptLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    styleSheetLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    subFrameLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+    xmlHttpRequestLineEditPointer->setEnabled(hasRequestOptionsCheckBoxPointer->isChecked());
+
+    // Set the domain list line edit to have the same palette as the domain line edit.
+    domainListLineEditPointer->setPalette(domainLineEditPointer->palette());
+
+    // Set the button status.
+    previousButtonPointer->setEnabled(previousEnabled);
+    nextButtonPointer->setEnabled(nextEnabled);
+}
+
+void FilterEntryDialog::previous()
+{
+    // Update the current row.
+    --currentRow;
+
+    // Populate the dialog.
+    populateDialog(currentRow);
+}
+
+void FilterEntryDialog::next()
+{
+    // Update the current row.
+    ++currentRow;
+
+    // Populate the dialog.
+    populateDialog(currentRow);
+}
+
+void FilterEntryDialog::setFilterOptionBackgroundPalette(QLineEdit *lineEditPointer)
+{
+    // Set the background palette according to the text.
+    if (lineEditPointer->text() == globalFilterListHelperPointer->getRequestOptionDispositionString(FilterOptionEnum::Disposition::Null))  // Not text is displayed.
+    {
+        // Set the normal background palette.
+        lineEditPointer->setPalette(normalBackgroundPalette);
+    }
+    else if (lineEditPointer->text() == globalFilterListHelperPointer->getRequestOptionDispositionString(FilterOptionEnum::Disposition::Apply))  // `Apply` is displayed.
+    {
+        // Set the negative (red) background palette.
+        lineEditPointer->setPalette(negativeBackgroundPalette);
+    }
+    else  // `Override` is displayed.
+    {
+        // Set the positive (green) background palette.
+        lineEditPointer->setPalette(positiveBackgroundPalette);
+    }
+}
+
+void FilterEntryDialog::setInitialAndFinalMatchBackgroundPalette(QLineEdit *lineEditPointer)
+{
+    // Set the background palette according to the text.
+    if (lineEditPointer->text() == i18n("Yes"))  // `Yes` is displayed.
+    {
+        // Set the negative (red) background palette.
+        lineEditPointer->setPalette(negativeBackgroundPalette);
+    }
+    else  // No text is displayed.
+    {
+        // Set the normal background palette.
+        lineEditPointer->setPalette(normalBackgroundPalette);
+    }
+}
diff --git a/src/dialogs/FilterEntryDialog.h b/src/dialogs/FilterEntryDialog.h
new file mode 100644 (file)
index 0000000..fef1ce1
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2024 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 FILTERENTRYDIALOG_H
+#define FILTERENTRYDIALOG_H
+
+// Qt toolkit headers.
+#include <QCheckBox>
+#include <QDialog>
+#include <QTableWidget>
+
+class FilterEntryDialog : public QDialog
+{
+    // Include the Q_OBJECT macro.
+    Q_OBJECT
+
+public:
+    // The primary constructor.
+    explicit FilterEntryDialog(QWidget *parentWidgetPointer, QTableWidget *tableWidgetPointer, const int initialRow, const QString &filterListTitle, const QString &sublistTitle);
+
+private Q_SLOTS:
+    // The private slots.
+    void next();
+    void previous();
+
+private:
+    // The private variables.
+    QLineEdit *appliedEntryListLineEditPointer;
+    QLineEdit *appliedFilterOptionsLineEditPointer;
+    int currentRow;
+    QLineEdit *domainLineEditPointer;
+    QLineEdit *domainListLineEditPointer;
+    QLineEdit *finalMatchLineEditPointer;
+    QLineEdit *fontLineEditPointer;
+    QCheckBox *hasRequestOptionsCheckBoxPointer;
+    QLineEdit *imageLineEditPointer;
+    QLineEdit *initialMatchLineEditPointer;
+    QLineEdit *mainFrameLineEditPointer;
+    QLineEdit *mediaLineEditPointer;
+    QPalette negativeBackgroundPalette;
+    QPushButton *nextButtonPointer;
+    QPalette normalBackgroundPalette;
+    QLineEdit *objectLineEditPointer;
+    QLineEdit *originalEntryLineEditPointer;
+    QLineEdit *originalFilterOptionsLineEditPointer;
+    QLineEdit *otherLineEditPointer;
+    QLineEdit *pingLineEditPointer;
+    QPalette positiveBackgroundPalette;
+    QPushButton *previousButtonPointer;
+    QLineEdit *scriptLineEditPointer;
+    QLineEdit *styleSheetLineEditPointer;
+    QLineEdit *subFrameLineEditPointer;
+    QTableWidget *tableWidgetPointer;
+    QLineEdit *thirdPartyLineEditPointer;
+    QLineEdit *xmlHttpRequestLineEditPointer;
+
+    // The private functions.
+    void populateDialog(const int row);
+    void setFilterOptionBackgroundPalette(QLineEdit *lineEditPointer);
+    void setInitialAndFinalMatchBackgroundPalette(QLineEdit *lineEditPointer);
+};
+#endif
index 0ab6753780d1abe958ee75cd9830b8b5f46aebbe..2d019d87e22b6814c5077723a3963545cebbfda9 100644 (file)
 #include "FilterListsDialog.h"
 #include "GlobalVariables.h"
 #include "ui_FilterListsDialog.h"
-#include "delegates/ViewAndCopyDelegate.h"
+#include "dialogs/FilterEntryDialog.h"
 
 // Qt toolkit headers.
+#include <QDebug>
 #include <QFile>
 #include <QTextStream>
 
@@ -49,11 +50,11 @@ FilterListsDialog::FilterListsDialog(QWidget *parentWidgetPointer) : QDialog(par
     sublistTableWidgetPointer = filterListsDialogUi.sublistTableWidget;
     QDialogButtonBox *dialogButtonBoxPointer = filterListsDialogUi.dialogButtonBox;
 
-    // Create a view and copy delegate.
-    ViewAndCopyDelegate *viewAndCopyDelegate = new ViewAndCopyDelegate(this);
+    // Select an entire row at a time.
+    sublistTableWidgetPointer->setSelectionBehavior(QAbstractItemView::SelectRows);
 
-    // Set the sublist table widget allow copying but not editing.
-    sublistTableWidgetPointer->setItemDelegate(viewAndCopyDelegate);
+    // Open the filter entry dialog when a cell is clicked.
+    connect(sublistTableWidgetPointer, SIGNAL(cellClicked(int, int)), this, SLOT(showFilterEntryDialog(int)));
 
     // Connect the combo boxes.
     connect(filterListComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(populateFilterListTextEdit(int)));
@@ -63,47 +64,54 @@ FilterListsDialog::FilterListsDialog(QWidget *parentWidgetPointer) : QDialog(par
     connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(close()));
 
     // Populate the filter list combo box.
-    populateFilterListComboBox(globalFilterListHelperPointer->ultraListStructPointer);
     populateFilterListComboBox(globalFilterListHelperPointer->ultraPrivacyStructPointer);
-    populateFilterListComboBox(globalFilterListHelperPointer->easyListStructPointer);
+    populateFilterListComboBox(globalFilterListHelperPointer->ultraListStructPointer);
     populateFilterListComboBox(globalFilterListHelperPointer->easyPrivacyStructPointer);
+    populateFilterListComboBox(globalFilterListHelperPointer->easyListStructPointer);
     populateFilterListComboBox(globalFilterListHelperPointer->fanboyAnnoyanceStructPointer);
 }
 
-void FilterListsDialog::populateFilterListComboBox(const FilterListStruct *filterListStructPointer) const
+std::forward_list<EntryStruct *>* FilterListsDialog::getFilterListForwardList(FilterListStruct *filterListStructPointer) const
 {
-    // Populate the filter list combo box.
-    filterListComboBoxPointer->addItem(i18nc("Filter list combo box items", "%1 - %2", filterListStructPointer->title, filterListStructPointer->version));
+    // Return the filter list forward list.
+    switch (sublistComboBoxPointer->currentIndex())
+    {
+        case FilterListHelper::MAIN_ALLOWLIST: return filterListStructPointer->mainAllowListPointer;  // The main allow list.
+        case FilterListHelper::MAIN_BLOCKLIST: return filterListStructPointer->mainBlockListPointer;  // The main block list.
+        case FilterListHelper::INITIAL_DOMAIN_BLOCKLIST: return filterListStructPointer->initialDomainBlockListPointer;  // The initial domain block list.
+        case FilterListHelper::REGULAR_EXPRESSION_BLOCKLIST: return filterListStructPointer->regularExpressionBlockListPointer;  // The regular expression block list.
+    }
+
+    // This return statement should never be reached.
+    return new std::forward_list<EntryStruct *>;
 }
 
-void FilterListsDialog::populateFilterListTextEdit(int filterListComboBoxInt) const
+FilterListStruct *FilterListsDialog::getFilterListStruct(int filterListComboBoxIndex) const
 {
-    // Create the filter list struct pointer.
-    FilterListStruct *filterListStructPointer;
-
-    // Get the indicated filter list map.
-    switch (filterListComboBoxInt)
+    // Return the filer list struct.
+    switch (filterListComboBoxIndex)
     {
-        case 0:  // UltraList.
-            filterListStructPointer = globalFilterListHelperPointer->ultraListStructPointer;
-            break;
-
-        case 1:  // UltraPrivacy.
-            filterListStructPointer = globalFilterListHelperPointer->ultraPrivacyStructPointer;
-            break;
+        case 0: return globalFilterListHelperPointer->ultraPrivacyStructPointer;  // UltraPrivacy.
+        case 1: return globalFilterListHelperPointer->ultraListStructPointer;  // UltraList.
+        case 2: return globalFilterListHelperPointer->easyPrivacyStructPointer;  // EasyPrivacy.
+        case 3: return globalFilterListHelperPointer->easyListStructPointer;  // EasyList.
+        case 4: return globalFilterListHelperPointer->fanboyAnnoyanceStructPointer;  // Fanboy's Annoyance List.
+    }
 
-        case 2:  // EasyList.
-            filterListStructPointer = globalFilterListHelperPointer->easyListStructPointer;
-            break;
+    // This return statement should never be reached.
+    return new FilterListStruct;
+}
 
-        case 3:  // EasyPrivacy.
-            filterListStructPointer = globalFilterListHelperPointer->easyPrivacyStructPointer;
-            break;
+void FilterListsDialog::populateFilterListComboBox(const FilterListStruct *filterListStructPointer) const
+{
+    // Populate the filter list combo box.
+    filterListComboBoxPointer->addItem(i18nc("Filter list combo box items", "%1 - %2", filterListStructPointer->title, filterListStructPointer->version));
+}
 
-        case 4:  // Fanboy's Annoyance List.
-            filterListStructPointer = globalFilterListHelperPointer->fanboyAnnoyanceStructPointer;
-            break;
-    }
+void FilterListsDialog::populateFilterListTextEdit(int filterListComboBoxIndex) const
+{
+    // Get the filter list struct.
+    FilterListStruct *filterListStructPointer = getFilterListStruct(filterListComboBoxIndex);
 
     // Get the filter list file.
     QFile filterListFile(filterListStructPointer->filePath);
@@ -121,168 +129,194 @@ void FilterListsDialog::populateFilterListTextEdit(int filterListComboBoxInt) co
     sublistComboBoxPointer->clear();
 
     // Calculate the size of the filter lists.
-    int mainAllowListSize = distance(filterListStructPointer->mainAllowList.begin(), filterListStructPointer->mainAllowList.end());
-    int mainBlockListSize = distance(filterListStructPointer->mainBlockList.begin(), filterListStructPointer->mainBlockList.end());
-    int initialDomainBlockListSize = distance(filterListStructPointer->initialDomainBlockList.begin(), filterListStructPointer->initialDomainBlockList.end());
+    int mainAllowListSize = distance(filterListStructPointer->mainAllowListPointer->begin(), filterListStructPointer->mainAllowListPointer->end());
+    int mainBlockListSize = distance(filterListStructPointer->mainBlockListPointer->begin(), filterListStructPointer->mainBlockListPointer->end());
+    int initialDomainBlockListSize = distance(filterListStructPointer->initialDomainBlockListPointer->begin(), filterListStructPointer->initialDomainBlockListPointer->end());
+    int regularExpressionBlockListSize = distance(filterListStructPointer->regularExpressionBlockListPointer->begin(), filterListStructPointer->regularExpressionBlockListPointer->end());
 
     // Get the translated filter list names.
     QString mainAllowListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::MAIN_ALLOWLIST);
     QString mainBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::MAIN_BLOCKLIST);
     QString initialDomainBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::INITIAL_DOMAIN_BLOCKLIST);
+    QString regularExpressionBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::REGULAR_EXPRESSION_BLOCKLIST);
 
     // Populate the sublist combo box.
     sublistComboBoxPointer->addItem(i18nc("The main allow list", "%1 - %2", mainAllowListName, mainAllowListSize));
     sublistComboBoxPointer->addItem(i18nc("The main block list", "%1 - %2", mainBlockListName, mainBlockListSize));
     sublistComboBoxPointer->addItem(i18nc("The initial domain block list", "%1 - %2", initialDomainBlockListName, initialDomainBlockListSize));
+    sublistComboBoxPointer->addItem(i18nc("the regular expression block list", "%1 - %2", regularExpressionBlockListName, regularExpressionBlockListSize));
 }
 
 void FilterListsDialog::populateTableWidget(int sublistComboBoxIndex) const
 {
-    // Wipe the current table.
-    sublistTableWidgetPointer->clear();
-    sublistTableWidgetPointer->setColumnCount(0);
-    sublistTableWidgetPointer->setRowCount(0);
-
-    // Create the filter list struct.
-    FilterListStruct *filterListStructPointer;
-
-    // Populate the filer list array.
-    switch (filterListComboBoxPointer->currentIndex())
-    {
-        case 0:  // UltraList.
-            filterListStructPointer = globalFilterListHelperPointer->ultraListStructPointer;
-            break;
-
-        case 1:  // UltraPrivacy.
-            filterListStructPointer = globalFilterListHelperPointer->ultraPrivacyStructPointer;
-            break;
-
-        case 2:  // EasyList.
-            filterListStructPointer = globalFilterListHelperPointer->easyListStructPointer;
-            break;
-
-        case 3:  // EasyPrivacy.
-            filterListStructPointer = globalFilterListHelperPointer->easyPrivacyStructPointer;
-            break;
-
-        case 4:  // Fanboy's Annoyance List.
-            filterListStructPointer = globalFilterListHelperPointer->fanboyAnnoyanceStructPointer;
-            break;
-    }
-
-    // Create a filter list forward list.
-    std::forward_list<EntryStruct *> filterListForwardList;
-
-    // Populate the filter list forward list.
-    switch (sublistComboBoxIndex)
+    // Populate the table widget if there is at least one item in teh sublist combo box.
+    if (sublistComboBoxIndex >= 0)
     {
-        case FilterListHelper::MAIN_ALLOWLIST:  // The main allow list.
-            filterListForwardList = filterListStructPointer->mainAllowList;
-            break;
-
-        case FilterListHelper::MAIN_BLOCKLIST:  // The main block list.
-            filterListForwardList = filterListStructPointer->mainBlockList;
-            break;
-
-        case FilterListHelper::INITIAL_DOMAIN_BLOCKLIST:  // The initial domain block list.
-            filterListForwardList = filterListStructPointer->initialDomainBlockList;
-            break;
+        // Wipe the current table.
+        sublistTableWidgetPointer->clear();
+        sublistTableWidgetPointer->setColumnCount(0);
+        sublistTableWidgetPointer->setRowCount(0);
+
+        // Get the filter list struct.
+        FilterListStruct *filterListStructPointer = getFilterListStruct(filterListComboBoxPointer->currentIndex());
+
+        // Create a filter list forward list.
+        std::forward_list<EntryStruct *> *filterListForwardListPointer;
+
+        // Populate the filter list forward list.
+        switch (sublistComboBoxIndex)
+        {
+            case FilterListHelper::MAIN_ALLOWLIST:  // The main allow list.
+                filterListForwardListPointer = filterListStructPointer->mainAllowListPointer;
+                break;
+
+            case FilterListHelper::MAIN_BLOCKLIST:  // The main block list.
+                filterListForwardListPointer = filterListStructPointer->mainBlockListPointer;
+                break;
+
+            case FilterListHelper::INITIAL_DOMAIN_BLOCKLIST:  // The initial domain block list.
+                filterListForwardListPointer = filterListStructPointer->initialDomainBlockListPointer;
+                break;
+
+            case FilterListHelper::REGULAR_EXPRESSION_BLOCKLIST:  // the regular expression block list.
+                filterListForwardListPointer = filterListStructPointer->regularExpressionBlockListPointer;
+                break;
+        }
+
+        // Create the columns.
+        sublistTableWidgetPointer->setColumnCount(21);
+
+        // Create the table headers.
+        QTableWidgetItem *appliedEntryListHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist applied entry list header", "Applied Entry List"));
+        QTableWidgetItem *initialMatchHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist initial match header", "Initial Match"));
+        QTableWidgetItem *finalMatchHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist final match header", "Final Match"));
+        QTableWidgetItem *domainHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist domain header", "Domain"));
+        QTableWidgetItem *domainListHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist domain list Header", "Domain List"));
+        QTableWidgetItem *thirdPartyHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist third-party header", "Third Party"));
+        QTableWidgetItem *hasRequestOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist has request options header", "Has Request Options"));
+        QTableWidgetItem *fontHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist font header", "Font"));
+        QTableWidgetItem *imageHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist image header", "Image"));
+        QTableWidgetItem *mainFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist main frame header", "Main Frame"));
+        QTableWidgetItem *mediaHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist media header", "Media"));
+        QTableWidgetItem *objectHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Object"));
+        QTableWidgetItem *otherHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Other"));
+        QTableWidgetItem *pingHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist ping header", "Ping"));
+        QTableWidgetItem *scriptHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist script header", "Script"));
+        QTableWidgetItem *styleSheetHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist style sheet header", "Style Sheet"));
+        QTableWidgetItem *subFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist sub frame header", "Sub Frame"));
+        QTableWidgetItem *xmlHttpRequestHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist XML HTTP request header", "XML HTTP Request"));
+        QTableWidgetItem *appliedFilterOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist applied filter options header", "Applied Filter Options"));
+        QTableWidgetItem *originalFilterOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist original filter options header", "Original Filter Options"));
+        QTableWidgetItem *originalEntryHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist original entry header", "Original Entry"));
+
+        // Set the horizontal headers.
+        sublistTableWidgetPointer->setHorizontalHeaderItem(0, appliedEntryListHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(1, initialMatchHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(2, finalMatchHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(3, domainHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(4, domainListHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(5, thirdPartyHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(6, hasRequestOptionsHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(7, fontHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(8, imageHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(9, mainFrameHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(10, mediaHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(11, objectHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(12, otherHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(13, pingHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(14, scriptHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(15, styleSheetHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(16, subFrameHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(17, xmlHttpRequestHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(18, appliedFilterOptionsHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(19, originalFilterOptionsHeaderItemPointer);
+        sublistTableWidgetPointer->setHorizontalHeaderItem(20, originalEntryHeaderItemPointer);
+
+        // Initialize the row counter.
+        int rowCounter = 0;
+
+        // Populate the table.
+        for (auto filterListEntry = filterListForwardListPointer->begin(); filterListEntry != filterListForwardListPointer->end(); ++filterListEntry) {
+            // Get the entry struct.
+            EntryStruct *entryStructPointer = *filterListEntry;
+
+            // Add a new row.
+            sublistTableWidgetPointer->insertRow(rowCounter);
+
+            // Create the entry items.
+            QTableWidgetItem *appliedEntryListItemPointer = new QTableWidgetItem(entryStructPointer->appliedEntryList.join(QLatin1String(" * ")));
+            QTableWidgetItem *initialMatchItemPointer = new QTableWidgetItem(entryStructPointer->initialMatch ? i18n("Yes") : QLatin1String());
+            QTableWidgetItem *finalMatchItemPointer = new QTableWidgetItem(entryStructPointer->finalMatch ? i18n("Yes") : QLatin1String());
+            QTableWidgetItem *domainItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->domain));
+            QTableWidgetItem *domainListItemPointer = new QTableWidgetItem(entryStructPointer->domainList.join(QLatin1String(" | ")));
+            QTableWidgetItem *thirdPartyItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->thirdParty));
+            QTableWidgetItem *hasRequestOptionsItemPointer = new QTableWidgetItem(entryStructPointer->hasRequestOptions ? i18n("Yes") : QLatin1String());
+            QTableWidgetItem *fontItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->font));
+            QTableWidgetItem *imageItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->image));
+            QTableWidgetItem *mainFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->mainFrame));
+            QTableWidgetItem *mediaItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->media));
+            QTableWidgetItem *objectItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->object));
+            QTableWidgetItem *otherItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->other));
+            QTableWidgetItem *pingItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->ping));
+            QTableWidgetItem *scriptItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->script));
+            QTableWidgetItem *styleSheetItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->styleSheet));
+            QTableWidgetItem *subFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->subFrame));
+            QTableWidgetItem *xmlHttpRequestItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->xmlHttpRequest));
+            QTableWidgetItem *appliedFilterOptionsItemPointer = new QTableWidgetItem(entryStructPointer->appliedFilterOptionsList.join(QLatin1String(" , ")));
+            QTableWidgetItem *originalFilterOptionsItemPointer = new QTableWidgetItem(entryStructPointer->originalFilterOptions);
+            QTableWidgetItem *originalEntryItemPointer = new QTableWidgetItem(entryStructPointer->originalEntry);
+
+            // Add the entries to the table.
+            sublistTableWidgetPointer->setItem(rowCounter, 0, appliedEntryListItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 1, initialMatchItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 2, finalMatchItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 3, domainItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 4, domainListItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 5, thirdPartyItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 6, hasRequestOptionsItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 7, fontItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 8, imageItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 9, mainFrameItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 10, mediaItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 11, objectItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 12, otherItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 13, pingItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 14, scriptItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 15, styleSheetItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 16, subFrameItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 17, xmlHttpRequestItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 18, appliedFilterOptionsItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 19, originalFilterOptionsItemPointer);
+            sublistTableWidgetPointer->setItem(rowCounter, 20, originalEntryItemPointer);
+
+            // Increment the row counter.
+            ++rowCounter;
+        }
+
+        // Get the table header view.
+        QHeaderView *headerViewPointer = sublistTableWidgetPointer->horizontalHeader();
+
+        // Resize the header to fit the contents.
+        headerViewPointer->resizeSections(QHeaderView::ResizeToContents);
+
+        // Connect changes in the sort order.
+        connect(headerViewPointer, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(sortTable(int, Qt::SortOrder)));
     }
+}
 
-    // Create the columns.
-    sublistTableWidgetPointer->setColumnCount(15);
-
-    // Create the table headers.
-    QTableWidgetItem *appliedEntryHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist applied entry header", "Applied Entry"));
-    QTableWidgetItem *thirdPartyHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist third-party header", "Third-Party"));
-    QTableWidgetItem *fontHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist font header", "Font"));
-    QTableWidgetItem *imageHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist image header", "Image"));
-    QTableWidgetItem *mainFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist main frame header", "Main Frame"));
-    QTableWidgetItem *mediaHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist media header", "Media"));
-    QTableWidgetItem *objectHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Object"));
-    QTableWidgetItem *otherHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Other"));
-    QTableWidgetItem *pingHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist ping header", "Ping"));
-    QTableWidgetItem *scriptHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist script header", "Script"));
-    QTableWidgetItem *styleSheetHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist style sheet header", "Style Sheet"));
-    QTableWidgetItem *subFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist sub frame header", "Sub Frame"));
-    QTableWidgetItem *xmlHttpRequestHeaderItemPointer = new QTableWidgetItem(i18nc("XML HTTP request header", "XML HTTP Request"));
-    QTableWidgetItem *filterOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist filter options header", "Filter Options"));
-    QTableWidgetItem *originalEntryHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist original entry header", "Original Entry"));
-
-    // Set the horizontal headers.
-    sublistTableWidgetPointer->setHorizontalHeaderItem(0, appliedEntryHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(1, thirdPartyHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(2, fontHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(3, imageHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(4, mainFrameHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(5, mediaHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(6, objectHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(7, otherHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(8, pingHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(9, scriptHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(10, styleSheetHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(11, subFrameHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(12, xmlHttpRequestHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(13, filterOptionsHeaderItemPointer);
-    sublistTableWidgetPointer->setHorizontalHeaderItem(14, originalEntryHeaderItemPointer);
-
-    // Initialize the row counter.
-    int rowCounter = 0;
-
-    // Populate the table.
-    for (auto filterListEntry = filterListForwardList.begin(); filterListEntry != filterListForwardList.end(); ++filterListEntry) {
-        // Get the entry struct.
-        EntryStruct *entryStructPointer = *filterListEntry;
-
-        // Add a new row.
-        sublistTableWidgetPointer->insertRow(rowCounter);
-
-        // Create the entry items.
-        QTableWidgetItem *appliedEntryItemPointer = new QTableWidgetItem(entryStructPointer->appliedEntry);
-        QTableWidgetItem *thirdPartyItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->thirdParty));
-        QTableWidgetItem *fontItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->font));
-        QTableWidgetItem *imageItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->image));
-        QTableWidgetItem *mainFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->mainFrame));
-        QTableWidgetItem *mediaItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->media));
-        QTableWidgetItem *objectItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->object));
-        QTableWidgetItem *otherItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->other));
-        QTableWidgetItem *pingItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->ping));
-        QTableWidgetItem *scriptItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->script));
-        QTableWidgetItem *styleSheetItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->styleSheet));
-        QTableWidgetItem *subFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->subFrame));
-        QTableWidgetItem *xmlHttpRequestItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getFilterOptionDispositionString(entryStructPointer->xmlHttpRequest));
-        QTableWidgetItem *filterOptionsItemPointer = new QTableWidgetItem(entryStructPointer->filterOptions);
-        QTableWidgetItem *originalEntryItemPointer = new QTableWidgetItem(entryStructPointer->originalEntry);
-
-        // Add the entries to the table.
-        sublistTableWidgetPointer->setItem(rowCounter, 0, appliedEntryItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 1, thirdPartyItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 2, fontItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 3, imageItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 4, mainFrameItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 5, mediaItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 6, objectItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 7, otherItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 8, pingItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 9, scriptItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 10, styleSheetItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 11, subFrameItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 12, xmlHttpRequestItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 13, filterOptionsItemPointer);
-        sublistTableWidgetPointer->setItem(rowCounter, 14, originalEntryItemPointer);
-
-        // Increment the row counter.
-        ++rowCounter;
-    }
+void FilterListsDialog::showFilterEntryDialog(int row)
+{
+    // Get the filter list struct.
+    FilterListStruct *filterListStructPointer = getFilterListStruct(filterListComboBoxPointer->currentIndex());
 
-    // Get the table header view.
-    QHeaderView *headerViewPointer = sublistTableWidgetPointer->horizontalHeader();
+    // Create a sublist title.
+    QString sublistTitle = globalFilterListHelperPointer->getSublistName(sublistComboBoxPointer->currentIndex());
 
-    // Resize the header to fit the contents.
-    headerViewPointer->resizeSections(QHeaderView::ResizeToContents);
+    // Instantiate the filter entry dialog.
+    FilterEntryDialog *filterEntryDialogPointer = new FilterEntryDialog(this, sublistTableWidgetPointer, row, filterListStructPointer->title, sublistTitle);
 
-    // Connect changes in the sort order.
-    connect(headerViewPointer, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(sortTable(int, Qt::SortOrder)));
+    // Show the dialog.
+    filterEntryDialogPointer->show();
 }
 
 void FilterListsDialog::sortTable(int column, Qt::SortOrder sortOrder) const
index 980af28d48cf2a2b48fc69f88d679ea48f660f26..ba87f72b023c2c3d12904e5b9e4458e061155a9c 100644 (file)
@@ -41,6 +41,7 @@ public:
 private Q_SLOTS:
     void populateFilterListTextEdit(int filterListComboBoxIndex) const;
     void populateTableWidget(int sublistComboBoxIndex) const;
+    void showFilterEntryDialog(int row);
     void sortTable(int column, Qt::SortOrder sortOrder) const;
 
 private:
@@ -51,6 +52,8 @@ private:
     QTableWidget *sublistTableWidgetPointer;
 
     // The private functions.
+    std::forward_list<EntryStruct *>* getFilterListForwardList(FilterListStruct *filterListStructPointer) const;
+    FilterListStruct* getFilterListStruct(int filterListComboBoxIndex) const;
     void populateFilterListComboBox(const FilterListStruct *filterListStructPointer) const;
 };
 #endif
index 14947fda0b29bf26771be1b67021692086b29e04..78e2f00dc606a93d688f629eb539e5d6d0d0fec7 100644 (file)
@@ -54,8 +54,8 @@ RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QTableWid
     filterListLineEditPointer = requestDetailDialogUi.filterListLineEdit;
     sublistLabelPointer = requestDetailDialogUi.sublistLabel;
     sublistLineEditPointer = requestDetailDialogUi.sublistListLineEdit;
-    appliedEntryLabelPointer = requestDetailDialogUi.appliedEntryLabel;
-    appliedEntryLineEditPointer = requestDetailDialogUi.appliedEntryLineEdit;
+    appliedEntryListLabelPointer = requestDetailDialogUi.appliedEntryListLabel;
+    appliedEntryListLineEditPointer = requestDetailDialogUi.appliedEntryListLineEdit;
     originalEntryLabelPointer = requestDetailDialogUi.originalEntryLabel;
     originalEntryLineEditPointer = requestDetailDialogUi.originalEntryLineEdit;
     previousButtonPointer = requestDetailDialogUi.previousButton;
@@ -123,7 +123,7 @@ void RequestDetailDialog::populateDialog(const int row)
 
     // Populate the new request struct.
     requestStructDataStreamReader >> requestStructPointer->dispositionInt;
-    requestStructDataStreamReader >> requestStructPointer->entryStruct.appliedEntry;
+    requestStructDataStreamReader >> requestStructPointer->entryStruct.appliedEntryList;
     requestStructDataStreamReader >> requestStructPointer->entryStruct.originalEntry;
     requestStructDataStreamReader >> requestStructPointer->filterListTitle;
     requestStructDataStreamReader >> requestStructPointer->navigationTypeInt;
@@ -140,7 +140,7 @@ void RequestDetailDialog::populateDialog(const int row)
     resourceTypeLineEditPointer->setText(globalFilterListHelperPointer->getResourceTypeString(requestStructPointer->resourceTypeInt));
     filterListLineEditPointer->setText(requestStructPointer->filterListTitle);
     sublistLineEditPointer->setText(globalFilterListHelperPointer->getSublistName(requestStructPointer->sublistInt));
-    appliedEntryLineEditPointer->setText(requestStructPointer->entryStruct.appliedEntry);
+    appliedEntryListLineEditPointer->setText(requestStructPointer->entryStruct.appliedEntryList.join(QLatin1String(" * ")));
     originalEntryLineEditPointer->setText(requestStructPointer->entryStruct.originalEntry);
 
     // Set the button status.
@@ -161,8 +161,8 @@ void RequestDetailDialog::populateDialog(const int row)
             filterListLineEditPointer->hide();
             sublistLabelPointer->hide();
             sublistLineEditPointer->hide();
-            appliedEntryLabelPointer->hide();
-            appliedEntryLineEditPointer->hide();
+            appliedEntryListLabelPointer->hide();
+            appliedEntryListLineEditPointer->hide();
             originalEntryLabelPointer->hide();
             originalEntryLineEditPointer->hide();
 
@@ -180,8 +180,8 @@ void RequestDetailDialog::populateDialog(const int row)
             filterListLineEditPointer->show();
             sublistLabelPointer->show();
             sublistLineEditPointer->show();
-            appliedEntryLabelPointer->show();
-            appliedEntryLineEditPointer->show();
+            appliedEntryListLabelPointer->show();
+            appliedEntryListLineEditPointer->show();
             originalEntryLabelPointer->show();
             originalEntryLineEditPointer->show();
 
@@ -199,8 +199,8 @@ void RequestDetailDialog::populateDialog(const int row)
             filterListLineEditPointer->show();
             sublistLabelPointer->show();
             sublistLineEditPointer->show();
-            appliedEntryLabelPointer->show();
-            appliedEntryLineEditPointer->show();
+            appliedEntryListLabelPointer->show();
+            appliedEntryListLineEditPointer->show();
             originalEntryLabelPointer->show();
             originalEntryLineEditPointer->show();
 
index c15fcad132ad08fff09c16c3e8167ca5e88e7382..8fb21c4a3d9731499a1c7f4daa304aa52d186153 100644 (file)
@@ -41,8 +41,8 @@ private Q_SLOTS:
 
 private:
     // The private variables.
-    QLabel *appliedEntryLabelPointer;
-    QLineEdit *appliedEntryLineEditPointer;
+    QLabel *appliedEntryListLabelPointer;
+    QLineEdit *appliedEntryListLineEditPointer;
     int currentRow;
     QLineEdit *dispositionLineEditPointer;
     QLabel *filterListLabelPointer;
index 82535e87c69d254bd697e27a05584fc7f1b9e9c7..43e18097b6cf74268bc99681a5d012eb80333b2a 100644 (file)
@@ -100,7 +100,7 @@ RequestsDialog::RequestsDialog(QWidget *parentWidgetPointer, QList<RequestStruct
 
         // Populate the request struct data stream.
         requestStructDataStream << requestStructPointer->dispositionInt;
-        requestStructDataStream << requestStructPointer->entryStruct.appliedEntry;
+        requestStructDataStream << requestStructPointer->entryStruct.appliedEntryList;
         requestStructDataStream << requestStructPointer->entryStruct.originalEntry;
         requestStructDataStream << requestStructPointer->filterListTitle;
         requestStructDataStream << requestStructPointer->navigationTypeInt;
index f84112b58531ad17f1262eb68dd5e7dff5161403..e4ce25f529d3a2cbce839fa7fcac435b6eaaa055 100644 (file)
 #include "FilterListHelper.h"
 #include "structs/OverrideStruct.h"
 
+// KDE Framework headers.
+#include <KLocalizedString>
+
 // Qt toolkit headers.
 #include <QDebug>
 #include <QFile>
+#include <QRegularExpression>
 #include <QTextStream>
 
-// KDE Framework headers.
-#include <KLocalizedString>
-
 // Construct the class.
 FilterListHelper::FilterListHelper()
 {
@@ -78,18 +79,19 @@ FilterListHelper::FilterListHelper()
     MAIN_ALLOWLIST_STRING = i18nc("Main allowlist sublist", "Main Allow List");
     MAIN_BLOCKLIST_STRING = i18nc("Main blocklist sublist", "Main Block List");
     INITIAL_DOMAIN_BLOCKLIST_STRING = i18nc("Initial domain blocklist string", "Initial Domain Block List");
+    REGULAR_EXPRESSION_BLOCKLIST_STRING = i18nc("Regular expression blocklist string", "Regular Expression Block List");
 
     // Populate the filter lists.
-    ultraListStructPointer = populateFilterList(QLatin1String(":/filterlists/ultralist.txt"));
     ultraPrivacyStructPointer = populateFilterList(QLatin1String(":/filterlists/ultraprivacy.txt"));
-    easyListStructPointer = populateFilterList(QLatin1String(":/filterlists/easylist.txt"));
+    ultraListStructPointer = populateFilterList(QLatin1String(":/filterlists/ultralist.txt"));
     easyPrivacyStructPointer = populateFilterList(QLatin1String(":/filterlists/easyprivacy.txt"));
+    easyListStructPointer = populateFilterList(QLatin1String(":/filterlists/easylist.txt"));
     fanboyAnnoyanceStructPointer = populateFilterList(QLatin1String(":/filterlists/fanboy-annoyance.txt"));
 }
 
 bool FilterListHelper::checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer) const
 {
-    // Initiate a continue checking tracker.  If the tracker changes to false, all process of the request will be stopped.
+    // Initiate a continue checking tracker.  If the tracker changes to false, all processing of the request will be stopped.
     bool continueChecking = true;
 
     // Create a URL struct.
@@ -101,10 +103,10 @@ bool FilterListHelper::checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo
 
     // Get the hosts.
     QString firstPartyHost = firstPartyUrl.host();
-    QString requestHost = requestUrl.host();
+    urlStruct.fqdn = requestUrl.host();
 
     // Determine if this is a third-party request.
-    urlStruct.isThirdPartyRequest = (firstPartyHost != requestHost);
+    urlStruct.isThirdPartyRequest = (firstPartyHost != urlStruct.fqdn);
 
     // Get the request URL string.
     urlStruct.urlString = requestUrl.toString();
@@ -119,8 +121,9 @@ bool FilterListHelper::checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo
     urlStruct.urlStringWithSeparators.replace(QLatin1Char('='), QLatin1Char('^'));
     urlStruct.urlStringWithSeparators.replace(QLatin1Char('&'), QLatin1Char('^'));
 
-    // Add a `^` to the end of the string.
-    urlStruct.urlStringWithSeparators.append(QLatin1Char('^'));
+    // Add a `^` to the end of the string it it doesn't already contain one.
+    if (!urlStruct.urlStringWithSeparators.endsWith(QLatin1Char('^')))
+        urlStruct.urlStringWithSeparators.append(QLatin1Char('^'));
 
     // Create truncated URL strings and initially populate it with the original URL strings.
     urlStruct.truncatedUrlString = urlStruct.urlString;
@@ -134,20 +137,21 @@ bool FilterListHelper::checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo
     urlStruct.truncatedUrlStringWithSeparators.remove(0, fqdnIndex);
 
     // Check UltraList.
-    continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraListStructPointer);
+    continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraPrivacyStructPointer);
 
     // Check UltraPrivacy.
     if (continueChecking)
-        continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraPrivacyStructPointer);
-
-    // Check EasyList.
-    if (continueChecking)
-        continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyListStructPointer);
+        continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, ultraListStructPointer);
 
     // Check EasyPrivacy.
     if (continueChecking)
         continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyPrivacyStructPointer);
 
+    // Check EasyList.
+    if (continueChecking)
+        continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, easyListStructPointer);
+
+    // Check Fanboy's Annoyance list.
     if (continueChecking)
         continueChecking = checkIndividualList(urlRequestInfo, urlStruct, requestStructPointer, fanboyAnnoyanceStructPointer);
 
@@ -155,35 +159,22 @@ bool FilterListHelper::checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo
     return continueChecking;
 }
 
-bool FilterListHelper::blockRequest(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
-                                    EntryStruct *entryStructPointer) const
-{
-    // Block the request.
-    urlRequestInfo.block(true);
-
-    // Populate the request struct.
-    populateRequestStruct(requestStructPointer, BLOCKED, filterListTitle, sublistInt, entryStructPointer);
-
-    // Log the block.
-    //qDebug().noquote().nospace() << "Blocked request:  " << urlRequestInfo.firstPartyUrl() << ",  Filter list entry:  " << entryStructPointer->appliedEntry;
-
-    // Returning `false` stops all processing of the request.
-    return false;
-}
-
 bool FilterListHelper::checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, FilterListStruct *filterListStructPointer) const
 {
+    // Initiate a continue checking tracker.  If the tracker changes to false, all process of the request will be stopped.
+    bool continueChecking = true;
+
     // Check the main allow list.
-    for (auto filterListEntry = filterListStructPointer->mainAllowList.begin(); filterListEntry != filterListStructPointer->mainAllowList.end(); ++filterListEntry)
+    for (auto filterListEntry = filterListStructPointer->mainAllowListPointer->begin(); filterListEntry != filterListStructPointer->mainAllowListPointer->end(); ++filterListEntry)
     {
         // Get the entry struct.
         EntryStruct *entryStructPointer = *filterListEntry;
 
         // TODO.  Temporarily ignore empty applied entries.
-        if (!entryStructPointer->appliedEntry.isEmpty())
+        if (!entryStructPointer->appliedEntryList[0].isEmpty())
         {
-            // Check if the URL string contains the applied entry.
-            if (urlStruct.urlString.contains(entryStructPointer->appliedEntry) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntry))
+            // Check if the URL string contains the applied entry.  TODO.
+            if (urlStruct.urlString.contains(entryStructPointer->appliedEntryList[0]) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntryList[0]))
             {
                 // Allow the request.
                 urlRequestInfo.block(false);
@@ -200,47 +191,384 @@ bool FilterListHelper::checkIndividualList(QWebEngineUrlRequestInfo &urlRequestI
         }
     }
 
+    // Get the main block list end.
+    auto mainBlockListEnd = filterListStructPointer->mainBlockListPointer->end();
+
     // Check the main block list.
-    for (auto filterListEntry = filterListStructPointer->mainBlockList.begin(); filterListEntry != filterListStructPointer->mainBlockList.end(); ++filterListEntry)
+    for (auto mainBlockListEntry = filterListStructPointer->mainBlockListPointer->begin(); mainBlockListEntry != mainBlockListEnd; ++mainBlockListEntry)
     {
+        // Exit the loop if continue checking is false.
+        if (!continueChecking)
+            break;
+
         // Get the entry struct.
-        EntryStruct *entryStructPointer = *filterListEntry;
+        EntryStruct *entryStructPointer = *mainBlockListEntry;
 
-        // TODO.  Temporarily ignore empty applied entries.
-        if (!entryStructPointer->appliedEntry.isEmpty())
+        // Check the applied entries.
+        continueChecking = checkAppliedEntry(urlRequestInfo, urlStruct, requestStructPointer, filterListStructPointer->title, MAIN_BLOCKLIST, entryStructPointer, urlStruct.urlString,
+                                                urlStruct.urlStringWithSeparators);
+    }
+
+    // Get the initial domain block list end.
+    auto initialDomainBlockListEnd = filterListStructPointer->initialDomainBlockListPointer->end();
+
+    // Check the initial domain block list.
+    for (auto initialDomainBlockListEntry = filterListStructPointer->initialDomainBlockListPointer->begin(); initialDomainBlockListEntry != initialDomainBlockListEnd;
+         ++initialDomainBlockListEntry)
+    {
+        // Exit the loop if continue checking is false.
+        if (!continueChecking)
+            break;
+
+        // Get the entry struct.
+        EntryStruct *entryStructPointer = *initialDomainBlockListEntry;
+
+        // Check the applied entries.
+        continueChecking = checkAppliedEntry(urlRequestInfo, urlStruct, requestStructPointer, filterListStructPointer->title, INITIAL_DOMAIN_BLOCKLIST, entryStructPointer,
+                                             urlStruct.truncatedUrlString, urlStruct.truncatedUrlStringWithSeparators);
+    }
+
+    // Get the regular expression block list end.
+    auto regularExpressionBlockListEnd = filterListStructPointer->regularExpressionBlockListPointer->end();
+
+    // Check the regular expression block list.
+    for (auto regularExpressionBlockListEntry = filterListStructPointer->regularExpressionBlockListPointer->begin(); regularExpressionBlockListEntry != regularExpressionBlockListEnd;
+         ++regularExpressionBlockListEntry)
+    {
+        // Exit the loop if continue checking is false.
+        if (!continueChecking)
+            break;
+
+        // Get the entry struct.
+        EntryStruct *entryStructPointer = *regularExpressionBlockListEntry;
+
+        // Check the applied entries.
+        continueChecking = checkRegularExpression(urlRequestInfo, urlStruct, requestStructPointer, filterListStructPointer->title, REGULAR_EXPRESSION_BLOCKLIST, entryStructPointer);
+    }
+
+    // Return the continue checking status.
+    return continueChecking;
+}
+
+bool FilterListHelper::checkAppliedEntry(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle,
+                                         const int sublistInt, EntryStruct *entryStructPointer, QString &urlString, QString &urlStringWithSeparators) const
+{
+    // Check the entries according to the number.
+    if (entryStructPointer->singleAppliedEntry)
+    {
+        // Process initial and final matches.
+        if (entryStructPointer->initialMatch && entryStructPointer->finalMatch)  // This is both an initial and final match.
+        {
+            // Check the URL against the applied entry.
+            if ((urlString == entryStructPointer->appliedEntryList[0]) || (urlStringWithSeparators == entryStructPointer->appliedEntryList[0]))
+            {
+                // Check the domain status.
+                return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+            }
+        }
+        else if (entryStructPointer->initialMatch)  // This is an initial match.
+        {
+            // Check the URL against the applied entry.
+            if (urlString.startsWith(entryStructPointer->appliedEntryList[0]) || urlStringWithSeparators.startsWith(entryStructPointer->appliedEntryList[0]))
+            {
+                // Check the domain status.
+                return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+            }
+        }
+        else if (entryStructPointer->finalMatch)  // This is a final match.
+        {
+            // Check the URL against the applied entry.
+            if (urlString.endsWith(entryStructPointer->appliedEntryList[0]) || urlStringWithSeparators.endsWith(entryStructPointer->appliedEntryList[0]))
+            {
+                // Check the domain status.
+                return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+            }
+        }
+        else  // There is no initial or final matching.
         {
             // Check if the URL string contains the applied entry.
-            if (urlStruct.urlString.contains(entryStructPointer->appliedEntry) || urlStruct.urlStringWithSeparators.contains(entryStructPointer->appliedEntry))
+            if (urlString.contains(entryStructPointer->appliedEntryList[0]) || urlStringWithSeparators.contains(entryStructPointer->appliedEntryList[0]))
             {
-                // Check the third-party status.
-                bool continueChecking = checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListStructPointer->title, MAIN_BLOCKLIST, entryStructPointer);
+                // Check the domain status.
+                return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+            }
+        }
+    }
+    else  // There are multiple entries.
+    {
+        // Create a URL matches flag.
+        bool urlMatches = true;
+
+        // Process initial and final matches.
+        if (entryStructPointer->initialMatch && entryStructPointer->finalMatch)  // This is both an initial and final match.
+        {
+            // Check the first entry.
+            if (urlString.startsWith(entryStructPointer->appliedEntryList[0]) ||
+                urlStringWithSeparators.startsWith(entryStructPointer->appliedEntryList[0]))  // The URL string starts with the first applied entry.
+            {
+                // Get the number of characters to remove from the front of the URL strings.
+                int charactersToRemove = entryStructPointer->appliedEntryList[0].size();
+
+                // Remove the entry from the front of the URL string copies.
+                urlString.remove(0, charactersToRemove);
+                urlStringWithSeparators.remove(0, charactersToRemove);
+            }
+            else  // The URL string does not end with the last applied entry.
+            {
+                // Mark the URL matches flag as false.
+                urlMatches = false;
+            }
+
+            // Check the other entries if the URL still matches.
+            if (urlMatches)
+            {
+                // Calculate the penultimate entry.
+                int penultimateEntryNumber = (entryStructPointer->sizeOfAppliedEntryList - 1);
+                int ultimateEntryIndex = penultimateEntryNumber;
+
+                // Check all the middle entries.
+                for (int i = 1; i < penultimateEntryNumber; ++i)
+                {
+                    // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+                    int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+                    int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+                    // Get the larger of the two indexes.
+                    int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+                    // Check if the entry was found.
+                    if (index >= 0)  // The entry is contained in the URL string.
+                    {
+                        // Get the number of characters to remove from the front of the URL strings.
+                        int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+                        // Remove the entry from the front of the URL string copies.
+                        urlString.remove(0, charactersToRemove);
+                        urlStringWithSeparators.remove(0, charactersToRemove);
+                    }
+                    else  // The entry is not contained in the URL string.
+                    {
+                        // Mark the URL matches flag as false.
+                        urlMatches = false;
+                    }
+                }
+
+                // Check the final entry if the URL still matches.
+                if (urlMatches)
+                {
+                    if (urlString.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex]) ||
+                        urlStringWithSeparators.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex]))  // The URL string ends with the last applied entry.
+                    {
+                        // There is no need to modify the URL string copies as no further checks will be performed.
+                    }
+                    else  // The URL string does not end with the last applied entry.
+                    {
+                        // Mark the URL matches flag as false.
+                        urlMatches = false;
+                    }
+                }
+            }
+        }
+        else if (entryStructPointer->initialMatch)  // This is an initial match.
+        {
+            // Check the first entry.
+            if (urlString.startsWith(entryStructPointer->appliedEntryList[0]) ||
+                urlStringWithSeparators.startsWith(entryStructPointer->appliedEntryList[0]))  // The URL string starts with the first applied entry.
+            {
+                // Get the number of characters to remove from the front of the URL strings.
+                int charactersToRemove = entryStructPointer->appliedEntryList[0].size();
+
+                // Remove the entry from the front of the URL string copies.
+                urlString.remove(0, charactersToRemove);
+                urlStringWithSeparators.remove(0, charactersToRemove);
+            }
+            else  // The URL string does not end with the last applied entry.
+            {
+                // Mark the URL matches flag as false.
+                urlMatches = false;
+            }
+
+            // Check the other entries if the URL still matches.
+            if (urlMatches)
+            {
+                for (int i = 1; i < entryStructPointer->sizeOfAppliedEntryList; ++i)
+                {
+                    // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+                    int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+                    int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+                    // Get the larger of the two indexes.
+                    int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+                    // Check if the entry was found.
+                    if (index >= 0)  // The entry is contained in the URL string.
+                    {
+                        // Get the number of characters to remove from the front of the URL strings.
+                        int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+                        // Remove the entry from the front of the URL string copies.
+                        urlString.remove(0, charactersToRemove);
+                        urlStringWithSeparators.remove(0, charactersToRemove);
+                    }
+                    else  // The entry is not contained in the URL string.
+                    {
+                        // Mark the URL matches flag as false.
+                        urlMatches = false;
+                    }
+                }
+            }
+        }
+        else if (entryStructPointer->finalMatch)  // This is a final match.
+        {
+            // Calculate the penultimate entry.
+            int penultimateEntryNumber = (entryStructPointer->sizeOfAppliedEntryList - 1);
+            int ultimateEntryIndex = penultimateEntryNumber;
+
+            // Check all the entries except the last one.
+            for (int i = 0; i < penultimateEntryNumber; ++i)
+            {
+                // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+                int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+                int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+                // Get the larger of the two indexes.
+                int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+                // Check if the entry was found.
+                if (index >= 0)  // The entry is contained in the URL string.
+                {
+                    // Get the number of characters to remove from the front of the URL strings.
+                    int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+                    // Remove the entry from the front of the URL string copies.
+                    urlString.remove(0, charactersToRemove);
+                    urlStringWithSeparators.remove(0, charactersToRemove);
+                }
+                else  // The entry is not contained in the URL string.
+                {
+                    // Mark the URL matches flag as false.
+                    urlMatches = false;
+                }
+            }
 
-                // Stop processing the filter lists if continue checking is `false`.  Returning false halts all processing at upper levels.
-                if (continueChecking == false)
-                    return false;
+            // Check the final entry if the URL still matches.
+            if (urlMatches)
+            {
+                if (urlString.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex]) ||
+                    urlStringWithSeparators.endsWith(entryStructPointer->appliedEntryList[ultimateEntryIndex]))  // The URL string ends with the last applied entry.
+                {
+                    // There is no need to modify the URL string copies as no further checks will be performed.
+                }
+                else  // The URL string does not end with the last applied entry.
+                {
+                    // Mark the URL matches flag as false.
+                    urlMatches = false;
+                }
             }
         }
+        else  // There is no initial or final matching.
+        {
+            for (int i = 0; i < entryStructPointer->sizeOfAppliedEntryList; ++i)
+            {
+                // Get the index of the applied entry, which will be `-1` if it doesn't exist.
+                int stringIndex = urlString.indexOf(entryStructPointer->appliedEntryList[i]);
+                int stringWithSeparatorsIndex = urlStringWithSeparators.indexOf(entryStructPointer->appliedEntryList[i]);
+
+                // Get the larger of the two indexes.
+                int index = std::max(stringIndex, stringWithSeparatorsIndex);
+
+                // Check if the entry was found.
+                if (index >= 0)  // The entry is contained in the URL string.
+                {
+
+                    // Get the number of characters to remove from the front of the URL strings.
+                    int charactersToRemove = index + entryStructPointer->appliedEntryList[i].size();
+
+                    // Remove the entry from the front of the URL string copies.
+                    urlString.remove(0, charactersToRemove);
+                    urlStringWithSeparators.remove(0, charactersToRemove);
+                }
+                else  // The entry is not contained in the URL string.
+                {
+                    // Mark the URL matches flag as false.
+                    urlMatches = false;
+                }
+            }
+        }
+
+        // Check the domain status if the URL matches.
+        if (urlMatches)
+            return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
     }
 
-    // Check the initial domain block list.
-    for (auto filterListEntry = filterListStructPointer->initialDomainBlockList.begin(); filterListEntry != filterListStructPointer->initialDomainBlockList.end(); ++filterListEntry)
+    // If the applied entry doesn't match, return `true` to continue processing the URL request.
+    return true;
+}
+
+bool FilterListHelper::checkRegularExpression(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle,
+                                              const int sublistInt, EntryStruct *entryStructPointer) const
+{
+    // Create an applied entry regular expression.
+    QRegularExpression appliedEntryRegularExpression(entryStructPointer->appliedEntryList[0]);
+
+    // Check if the regular expression matches the applied entry.
+    if (urlStruct.urlString.contains(appliedEntryRegularExpression))
     {
-        // Get the entry struct.
-        EntryStruct *entryStructPointer = *filterListEntry;
+        // Check the domain status.
+        return checkDomain(urlRequestInfo, urlStruct, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
 
-        // Check if the truncated URL string begins with the applied entry.
-        if (urlStruct.truncatedUrlString.startsWith(entryStructPointer->appliedEntry) || urlStruct.truncatedUrlStringWithSeparators.startsWith(entryStructPointer->appliedEntry))
+    // If the regular expression doesn't match, return `true` to continue processing the URL request.
+    return true;
+}
+
+bool FilterListHelper::checkDomain(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+                                   EntryStruct *entryStructPointer) const
+{
+    // Check domain status.
+    if (entryStructPointer->domain == FilterOptionEnum::Disposition::Null)  // Ignore domain status.
+    {
+        // Check the third-party status.
+        return checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListTitle, sublistInt, entryStructPointer);
+    }
+    else if (entryStructPointer->domain == FilterOptionEnum::Disposition::Apply)  // Block requests from listed domains.
+    {
+        // Check each domain.
+        foreach (QString blockedDomain, entryStructPointer->domainList)
         {
-            // Check the third-party status.
-            bool continueChecking = checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListStructPointer->title, INITIAL_DOMAIN_BLOCKLIST, entryStructPointer);
+            // Check if the request came from a blocked domain.
+            if (urlStruct.fqdn.endsWith(blockedDomain))
+            {
+                // Check the third-party status.
+                return checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListTitle, sublistInt, entryStructPointer);
+            }
+        }
+    }
+    else if (entryStructPointer->domain == FilterOptionEnum::Disposition::Override)  // Block domains that are not overridden.
+    {
+        // Create a block domain flag.
+        bool blockDomain = true;
 
-            // Stop processing the filter lists if continue checking is `false`.  Returning false halts all processing at upper levels.
-            if (continueChecking == false)
-                return false;
+        // Check each overridden domain.
+        foreach (QString overriddenDomain, entryStructPointer->domainList)
+        {
+            // Check if the request came from an overridden domain.
+            if (urlStruct.fqdn.endsWith(overriddenDomain))
+            {
+                // Don't block the domain.
+                blockDomain = false;
+            }
+        }
+
+        // Continue checking if the domain is blocked.
+        if (blockDomain)
+        {
+            // Check the third-party status.
+            return checkThirdParty(urlRequestInfo, requestStructPointer, urlStruct.isThirdPartyRequest, filterListTitle, sublistInt, entryStructPointer);
         }
     }
 
-    // Return `true` to continue processing the URL request.
+    // There is a domain specified that doesn't match this request.  Return `true` to continue processing the URL request.
     return true;
 }
 
@@ -250,13 +578,13 @@ bool FilterListHelper::checkThirdParty(QWebEngineUrlRequestInfo &urlRequestInfo,
     // Check third-party status.
     if (entryStructPointer->thirdParty == FilterOptionEnum::Disposition::Null)  // Ignore third-party status.
     {
-        // Check if filter options are applied.
-        if (entryStructPointer->hasFilterOptions)  // Filter options are applied.
+        // Check if request options are applied.
+        if (entryStructPointer->hasRequestOptions)  // Request options are applied.
         {
-            // Process the filter options.
-            return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+            // Check the request options.
+            return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
         }
-        else  // Filter options are not applied.
+        else  // Request options are not applied.
         {
             // Block the request.
             return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
@@ -264,13 +592,13 @@ bool FilterListHelper::checkThirdParty(QWebEngineUrlRequestInfo &urlRequestInfo,
     }
     else if ((entryStructPointer->thirdParty == FilterOptionEnum::Disposition::Apply) && isThirdPartyRequest)  // Block third-party request.
     {
-        // Check if filter options are applied.
-        if (entryStructPointer->hasFilterOptions)  // Filter options are applied.
+        // Check if request options are applied.
+        if (entryStructPointer->hasRequestOptions)  // Request options are applied.
         {
-            // Process the filter options.
-            return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+            // Check the request options.
+            return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
         }
-        else  // Filter options are not applied.
+        else  // Request options are not applied.
         {
             // Block the request.
             return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
@@ -278,23 +606,133 @@ bool FilterListHelper::checkThirdParty(QWebEngineUrlRequestInfo &urlRequestInfo,
     }
     else if ((entryStructPointer->thirdParty == FilterOptionEnum::Disposition::Override) && !isThirdPartyRequest)  // Block first-party requests.
     {
-        // Check if filter options are applied.
-        if (entryStructPointer->hasFilterOptions)  // Filter options are applied.
+        // Check if request options are applied.
+        if (entryStructPointer->hasRequestOptions)  // Request options are applied.
         {
-            // Process the filter options.
-            return processFilterOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+            // Check the request options.
+            return checkRequestOptions(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
         }
-        else  // Filter options are not applied.
+        else  // Request options are not applied.
         {
             // Block the request.
             return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
         }
     }
 
-    // Returning `true` continues to process the filter lists.  Returning `false` halts all processing of the filter lists.
+    // The third-party option specified doesn't match this request.  Return `true` to continue processing the URL request.
+    return true;
+}
+
+bool FilterListHelper::checkRequestOptions(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+                                           EntryStruct *entryStructPointer) const
+{
+    // Block font requests.
+    if ((entryStructPointer->font == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeFontResource))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block image requests.
+    if ((entryStructPointer->image == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeImage))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block main frame requests.
+    if ((entryStructPointer->mainFrame == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) ||
+                                                                                    (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame)))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block media requests.
+    if ((entryStructPointer->media == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeMedia))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block object requests.
+    if ((entryStructPointer->object == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeObject))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block other requests.
+    if ((entryStructPointer->other == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSubResource) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeWorker) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSharedWorker) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePrefetch) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeFavicon) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeServiceWorker) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeCspReport) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePluginResource) ||
+                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeUnknown)))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block ping requests
+    if ((entryStructPointer->ping == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePing))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block script requests.
+    if ((entryStructPointer->script == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeScript))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block style sheet requests.
+    if ((entryStructPointer->styleSheet == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeStylesheet))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block sub resource requests.
+    if ((entryStructPointer->subFrame == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSubFrame) ||
+                                                                                   (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame)))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // Block XML HTTP requests.
+    if ((entryStructPointer->xmlHttpRequest == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeXhr))
+    {
+        // Block the request.
+        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+    }
+
+    // The request options specified don't match this request.  Return `true` to continue processing the URL request.
     return true;
 }
 
+bool FilterListHelper::blockRequest(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+                                    EntryStruct *entryStructPointer) const
+{
+    // Block the request.
+    urlRequestInfo.block(true);
+
+    // Populate the request struct.
+    populateRequestStruct(requestStructPointer, BLOCKED, filterListTitle, sublistInt, entryStructPointer);
+
+    // Log the block.
+    //qDebug().noquote().nospace() << "Blocked request:  " << urlRequestInfo.firstPartyUrl() << ",  Filter list entry:  " << entryStructPointer->appliedEntry;
+
+    // Returning `false` stops all processing of the request.
+    return false;
+}
+
 QString FilterListHelper::getDispositionString(int dispositionInt) const
 {
     // Return the translated disposition string.
@@ -306,17 +744,6 @@ QString FilterListHelper::getDispositionString(int dispositionInt) const
     }
 }
 
-QString FilterListHelper::getFilterOptionDispositionString(const FilterOptionEnum::Disposition filterOptionDisposition) const
-{
-    // Return the translated filter option disposition string.
-    switch (filterOptionDisposition)
-    {
-        case FilterOptionEnum::Disposition::Apply: return FILTER_OPTION_APPLY;
-        case FilterOptionEnum::Disposition::Override: return FILTER_OPTION_OVERRIDE;
-        default: return FILTER_OPTION_NULL;
-    }
-}
-
 QString FilterListHelper::getNavigationTypeString(int navigationTypeInt) const
 {
     // Return the translated navigation type string.
@@ -332,6 +759,17 @@ QString FilterListHelper::getNavigationTypeString(int navigationTypeInt) const
     }
 }
 
+QString FilterListHelper::getRequestOptionDispositionString(const FilterOptionEnum::Disposition filterOptionDisposition) const
+{
+    // Return the translated filter option disposition string.
+    switch (filterOptionDisposition)
+    {
+        case FilterOptionEnum::Disposition::Apply: return FILTER_OPTION_APPLY;
+        case FilterOptionEnum::Disposition::Override: return FILTER_OPTION_OVERRIDE;
+        default: return FILTER_OPTION_NULL;
+    }
+}
+
 QString FilterListHelper::getResourceTypeString(int resourceTypeInt) const
 {
     // Return the translated resource type string.
@@ -369,6 +807,7 @@ QString FilterListHelper::getSublistName(int sublistInt) const
         case MAIN_ALLOWLIST: return MAIN_ALLOWLIST_STRING;
         case MAIN_BLOCKLIST: return MAIN_BLOCKLIST_STRING;
         case INITIAL_DOMAIN_BLOCKLIST: return INITIAL_DOMAIN_BLOCKLIST_STRING;
+        case REGULAR_EXPRESSION_BLOCKLIST: return REGULAR_EXPRESSION_BLOCKLIST_STRING;
         default: return QString();  // The default return should never be reached.
     }
 }
@@ -452,342 +891,362 @@ FilterListStruct* FilterListHelper::populateFilterList(const QString &filterList
         }
         else  // Process the filter options.
         {
-            // Split any filter options from the end of the string.
-            QStringList splitEntryStringList = filterListString.split(QLatin1Char('$'));
-
-            // Store the entry without the filter options as the filter list string.
-            filterListString = splitEntryStringList[0];
-
-            // Create a popup only filter option tracker.
-            bool popupOnlyFilterOption = false;
+            // Get the index of the last dollar sign.
+            int indexOfLastDollarSign = filterListString.lastIndexOf(QLatin1Char('$'));
 
             // Process the filter options if they exist.
-            if (splitEntryStringList.size() > 1)
+            if (indexOfLastDollarSign > -1)
             {
-                // Store the filter options.
-                entryStructPointer->filterOptions = splitEntryStringList[1];
+                // Get the filter options.
+                entryStructPointer->originalFilterOptions = filterListString.section(QLatin1Char('$'), -1);
+
+                // Store the entry without the filter options as the filter list string.
+                filterListString.truncate(indexOfLastDollarSign);
 
                 // Split the filter options.
-                QStringList filterOptionsList = splitEntryStringList[1].split(QLatin1Char(','));
+                QStringList originalFilterOptionsList = entryStructPointer->originalFilterOptions.split(QLatin1Char(','));
 
-                // Check if the entry has a single popup filter option as Qt WebEngine doesn't know how to process them.
-                if ((filterOptionsList.size() == 1) && (filterOptionsList[0] == QLatin1String("popup")))  // This entry has a single popup filter option.
+                // Create an applied filter options list.
+                QStringList appliedFilterOptionsList;
+
+                // Populate the applied filter options list.
+                foreach (QString filterOption, originalFilterOptionsList)
                 {
-                    // Set the popup only filter option flag.
-                    popupOnlyFilterOption = true;
+                    // Only add filter options that are handled by Privacy Browser.
+                    if (!(filterOption.startsWith(QLatin1String("csp=")) ||
+                          filterOption.startsWith(QLatin1String("method=")) ||
+                          filterOption.startsWith(QLatin1String("redirect=")) ||
+                          filterOption.startsWith(QLatin1String("rewrite="))))
+                        appliedFilterOptionsList.append(filterOption);
                 }
-                else  // This entry has filter options besides popup.
-                {
-                    // Initialize an override struct.
-                    OverrideStruct overrideStruct;
 
-                    // Populate the filter options entries.
-                    foreach (QString filterOption, filterOptionsList)
-                    {
-                        // Populate the third-party options.
-                        if (filterOption == QLatin1String("third-party")) entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Apply;
-                        if (filterOption == QLatin1String("~third-party")) entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Override;
-
-                        // Populate the filter options.
-                        if (filterOption == QLatin1String("document"))
-                        {
-                            // Populate the main frame option.
-                            entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Apply;
-
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
-
-                        if (filterOption == QLatin1String("font"))
-                        {
-                            // Populate the font option.
-                            entryStructPointer->font = FilterOptionEnum::Disposition::Apply;
-
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
-
-                        if (filterOption == QLatin1String("image"))
-                        {
-                            // Populate the image option.
-                            entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
+                // Store the applied filter options list.
+                entryStructPointer->appliedFilterOptionsList = appliedFilterOptionsList;
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
+                // Initialize an override struct.
+                OverrideStruct overrideStruct;
 
-                        if (filterOption == QLatin1String("media"))
-                        {
-                            // Populate the media option.
-                            entryStructPointer->media = FilterOptionEnum::Disposition::Apply;
+                // Populate the filter options entries.
+                foreach (QString filterOption, appliedFilterOptionsList)
+                {
+                    // Parse the filter options.
+                    if (filterOption.startsWith(QLatin1String("domain=")))  // Domain.
+                    {
+                        // Remove `domain=` from the filter option.
+                        filterOption.remove(0, 7);
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
+                        // Store the domain list.
+                        entryStructPointer->domainList = filterOption.split(QLatin1Char('|'));
 
-                        if (filterOption == QLatin1String("object"))
+                        // Set the disposition.
+                        if (entryStructPointer->domainList[0].startsWith(QLatin1Char('~')))  // Override domains.
                         {
-                            // Populate the object option.
-                            entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
+                            // Populate the domain filter disposition.
+                            entryStructPointer->domain = FilterOptionEnum::Disposition::Override;
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
+                            // Remove the initial `~` from each domain.
+                            entryStructPointer->domainList.replaceInStrings(QLatin1String("~"), QLatin1String(""));
                         }
-
-                        if (filterOption == QLatin1String("other"))
+                        else  // Standard domains.
                         {
-                            // Populate the other option.
-                            entryStructPointer->other = FilterOptionEnum::Disposition::Apply;
-
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
+                            // Populate the domain filter disposition.
+                            entryStructPointer->domain = FilterOptionEnum::Disposition::Apply;
                         }
+                    }
+                    else if (filterOption == QLatin1String("third-party"))  // Third-party.
+                    {
+                        // Populate the third-party filter disposition.
+                        entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Apply;
+                    }
+                    else if (filterOption == QLatin1String("~third-party"))  // Third-party override.
+                    {
+                        // Populate the third-party filter disposition.
+                        entryStructPointer->thirdParty = FilterOptionEnum::Disposition::Override;
+                    }
+                    else if ((filterOption == QLatin1String("document")) || (filterOption == QLatin1String("popup")))  // Document (and popup).
+                    {
+                        // Populate the main frame disposition.
+                        entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Apply;
 
-                        if (filterOption == QLatin1String("ping"))
-                        {
-                            // Populate the ping option.
-                            entryStructPointer->ping = FilterOptionEnum::Disposition::Apply;
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("font"))  // Font.
+                    {
+                        // Populate the font disposition.
+                        entryStructPointer->font = FilterOptionEnum::Disposition::Apply;
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("image"))  // Image.
+                    {
+                        // Populate the image disposition.
+                        entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
 
-                        if (filterOption == QLatin1String("script"))
-                        {
-                            // Populate the script option.
-                            entryStructPointer->script = FilterOptionEnum::Disposition::Apply;
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("media"))  // Media.
+                    {
+                        // Populate the media disposition.
+                        entryStructPointer->media = FilterOptionEnum::Disposition::Apply;
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("object"))  // Object.
+                    {
+                        // Populate the object disposition.
+                        entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
 
-                        if (filterOption == QLatin1String("stylesheet"))
-                        {
-                            // Populate the script option.
-                            entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Apply;
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if ((filterOption == QLatin1String("other")) || (filterOption == QLatin1String("webrtc")) || (filterOption == QLatin1String("websocket")))  // Other.
+                    {  // `websocket` will get its own section in Qt6.
+                        // Populate the other disposition.
+                        entryStructPointer->other = FilterOptionEnum::Disposition::Apply;
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("ping"))  // Ping.
+                    {
+                        // Populate the ping disposition.
+                        entryStructPointer->ping = FilterOptionEnum::Disposition::Apply;
 
-                        if (filterOption == QLatin1String("subdocument"))
-                        {
-                            // Populate the sub resource option.
-                            entryStructPointer->subFrame = FilterOptionEnum::Disposition::Apply;
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("script"))  // Script.
+                    {
+                        // Populate the script disposition.
+                        entryStructPointer->script = FilterOptionEnum::Disposition::Apply;
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("stylesheet"))  // Style sheet.
+                    {
+                        // Populate the script disposition.
+                        entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Apply;
 
-                        if (filterOption == QLatin1String("xmlhttprequest"))
-                        {
-                            //Populate the XML HTTP request option.
-                            entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("subdocument"))  // Sub document.
+                    {
+                        // Populate the sub resource disposition.
+                        entryStructPointer->subFrame = FilterOptionEnum::Disposition::Apply;
 
-                            // Set the filter options flag.
-                            entryStructPointer->hasFilterOptions = true;
-                        }
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("xmlhttprequest"))  // XML HTTP request.
+                    {
+                        //Populate the XML HTTP request disposition.
+                        entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
 
+                        // Set the has request options flag.
+                        entryStructPointer->hasRequestOptions = true;
+                    }
+                    else if (filterOption == QLatin1String("~document"))  // Document override.
+                    {
                         // Populate the override struct.
-                        if (filterOption == QLatin1String("~document"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.mainFrame = true;
-                        }
-
-                        if (filterOption == QLatin1String("~font"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.font = true;
-                        }
-
-                        if (filterOption == QLatin1String("~image"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.image = true;
-                        }
-
-                        if (filterOption == QLatin1String("~media"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.media = true;
-                        }
-
-                        if (filterOption == QLatin1String("~object"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.object = true;
-                        }
-
-                        if (filterOption == QLatin1String("~other"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.other = true;
-                        }
-
-                        if (filterOption == QLatin1String("~ping"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.ping = true;
-                        }
-
-                        if (filterOption == QLatin1String("~script"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.script = true;
-                        }
-
-                        if (filterOption == QLatin1String("~stylesheet"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.styleSheet = true;
-                        }
-
-                        if (filterOption == QLatin1String("~subdocument"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.subFrame = true;
-                        }
-
-                        if (filterOption == QLatin1String("~xmlhttprequest"))
-                        {
-                            // Populate the override struct.
-                            overrideStruct.hasOverride = true;
-                            overrideStruct.xmlHttpRequest = true;
-                        }
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.mainFrame = true;
                     }
-
-                    // Apply the overrides.
-                    if (overrideStruct.hasOverride)
+                    else if (filterOption == QLatin1String("~font"))  // Font override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.font = true;
+                    }
+                    else if (filterOption == QLatin1String("~image"))  // Image override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.image = true;
+                    }
+                    else if (filterOption == QLatin1String("~media"))  // Media override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.media = true;
+                    }
+                    else if (filterOption == QLatin1String("~object"))  // Object override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.object = true;
+                    }
+                    else if ((filterOption == QLatin1String("~other")) || (filterOption == QLatin1String("~webrtc")) || (filterOption == QLatin1String("~websocket")))  // Other override.
+                    {  // `websocket` will get its own section in Qt6.
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.other = true;
+                    }
+                    else if (filterOption == QLatin1String("~ping"))  // Ping override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.ping = true;
+                    }
+                    else if (filterOption == QLatin1String("~script"))  // Script override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.script = true;
+                    }
+                    else if (filterOption == QLatin1String("~stylesheet"))  // Style sheet override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.styleSheet = true;
+                    }
+                    else if (filterOption == QLatin1String("~subdocument"))  // Sub document override.
+                    {
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.subFrame = true;
+                    }
+                    else if (filterOption == QLatin1String("~xmlhttprequest"))  // XML HTTP request override.
                     {
-                        // Font.
-                        if (overrideStruct.font)
-                            entryStructPointer->font = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->font = FilterOptionEnum::Disposition::Apply;
-
-                        // Image.
-                        if (overrideStruct.image)
-                            entryStructPointer->image = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
-
-                        // Main Frame (document).
-                        if (overrideStruct.mainFrame)
-                            entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Apply;
-
-                        // Media.
-                        if (overrideStruct.media)
-                            entryStructPointer->media = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->media = FilterOptionEnum::Disposition::Apply;
-
-                        // Object.
-                        if (overrideStruct.object)
-                            entryStructPointer->object = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
-
-                        // Other.
-                        if (overrideStruct.other)
-                            entryStructPointer->other = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->other = FilterOptionEnum::Disposition::Apply;
-
-                        // Ping.
-                        if (overrideStruct.ping)
-                            entryStructPointer->ping = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->ping = FilterOptionEnum::Disposition::Apply;
-
-                        //  Script.
-                        if (overrideStruct.script)
-                            entryStructPointer->script = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->script = FilterOptionEnum::Disposition::Apply;
-
-                        // Style Sheet.
-                        if (overrideStruct.styleSheet)
-                            entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Apply;
-
-                        // Sub Resource.
-                        if (overrideStruct.subFrame)
-                            entryStructPointer->subFrame = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->subFrame = FilterOptionEnum::Disposition::Apply;
-
-                        // XML HTTP Request.
-                        if (overrideStruct.xmlHttpRequest)
-                            entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Override;
-                        else
-                            entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
+                        // Populate the override struct.
+                        overrideStruct.hasOverride = true;
+                        overrideStruct.xmlHttpRequest = true;
                     }
                 }
-            }
 
-            // Drop entries that only have a single popup filter option as Qt WebEngine doesn't know how to process them.
-            if (popupOnlyFilterOption)  // This entry has a single popup filter option.
+                // Apply the overrides.
+                if (overrideStruct.hasOverride)
+                {
+                    // Set the has request options flag.
+                    entryStructPointer->hasRequestOptions = true;
+
+                    // Font.
+                    if (overrideStruct.font)
+                        entryStructPointer->font = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->font = FilterOptionEnum::Disposition::Apply;
+
+                    // Image.
+                    if (overrideStruct.image)
+                        entryStructPointer->image = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->image = FilterOptionEnum::Disposition::Apply;
+
+                    // Main Frame (document).
+                    if (overrideStruct.mainFrame)
+                        entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->mainFrame = FilterOptionEnum::Disposition::Apply;
+
+                    // Media.
+                    if (overrideStruct.media)
+                        entryStructPointer->media = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->media = FilterOptionEnum::Disposition::Apply;
+
+                    // Object.
+                    if (overrideStruct.object)
+                        entryStructPointer->object = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->object = FilterOptionEnum::Disposition::Apply;
+
+                    // Other.
+                    if (overrideStruct.other)
+                        entryStructPointer->other = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->other = FilterOptionEnum::Disposition::Apply;
+
+                    // Ping.
+                    if (overrideStruct.ping)
+                        entryStructPointer->ping = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->ping = FilterOptionEnum::Disposition::Apply;
+
+                    //  Script.
+                    if (overrideStruct.script)
+                        entryStructPointer->script = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->script = FilterOptionEnum::Disposition::Apply;
+
+                    // Style Sheet.
+                    if (overrideStruct.styleSheet)
+                        entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->styleSheet = FilterOptionEnum::Disposition::Apply;
+
+                    // Sub Resource.
+                    if (overrideStruct.subFrame)
+                        entryStructPointer->subFrame = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->subFrame = FilterOptionEnum::Disposition::Apply;
+
+                    // XML HTTP Request.
+                    if (overrideStruct.xmlHttpRequest)
+                        entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Override;
+                    else
+                        entryStructPointer->xmlHttpRequest = FilterOptionEnum::Disposition::Apply;
+                }
+            }  // Finish processing filter options.
+
+
+            if (filterListString.isEmpty() && !entryStructPointer->hasRequestOptions)  // There are no applied entries and no request options.
             {
-                // Do nothing.
+                // Ignore these entries as they will block all requests generally or for a specified domain.  Typically these are left over after removing `csp=` filter options.
 
-                // Log the dropping of the line.
-                //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " NOT added from " << filterListFileName << " (single popup filter option).";
+                // Log the dropping of the entry.
+                //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " NOT added from " << filterListFileName << ".";
             }
             else if (filterListString.startsWith(QLatin1String("@@")))  // Process an allow list entry.
             {
                 // Remove the initial `@@`.
                 filterListString.remove(0, 2);
 
-                // Remove any initial and trailing asterisks.
-                removeInitialAndTrailingAsterisks(filterListString);
+                // Prepare the filter list string.  TODO.  Initial allow lists must be processed first.
+                prepareFilterListString(filterListString, entryStructPointer);
 
-                // Add the applied entry to the struct.
-                entryStructPointer->appliedEntry = filterListString;
-
-                // Add the filter list entry struct to the main allow list.
-                filterListStructPointer->mainAllowList.push_front(entryStructPointer);
+                // Add the entry struct to the main allow list.
+                filterListStructPointer->mainAllowListPointer->push_front(entryStructPointer);
 
                 // Log the addition to the filter list.
                 //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " added to Main Allow List from " << filterListFileName << ".";
             }
-            else if (filterListString.startsWith(QLatin1String("||")))  // Process an initial domain allow list entry.
+            else if (filterListString.startsWith(QLatin1String("||")))  // Process an initial domain block list entry.
             {
                 // Remove the initial `||`.
                 filterListString.remove(0, 2);
 
-                // Add the applied entry to the struct.
-                entryStructPointer->appliedEntry = filterListString;
+                // Set the initial match flag.
+                entryStructPointer->initialMatch = true;
+
+                // Prepare the filter list string.
+                prepareFilterListString(filterListString, entryStructPointer);
 
-                // Add the filter list entry struct to the initial domain block list.
-                filterListStructPointer->initialDomainBlockList.push_front(entryStructPointer);
+                // Add the entry struct to the initial domain block list.
+                filterListStructPointer->initialDomainBlockListPointer->push_front(entryStructPointer);
 
                 // Log the addition to the filter list.
                 //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " added to Initial Domain Block List from " << filterListFileName << ".";
             }
-            else  // Process a block list entry.
+            else if (filterListString.contains(QLatin1String("\\")))  // Process a regular expression block list entry.
             {
-                // Remove any initial and trailing asterisks.
-                removeInitialAndTrailingAsterisks(filterListString);
+                // Add the regular expression to the applied entry list.
+                entryStructPointer->appliedEntryList.append(filterListString);
 
-                // Add the applied entry to the struct.
-                entryStructPointer->appliedEntry = filterListString;
+                // Add the entry struct to the regular expression block list.
+                filterListStructPointer->regularExpressionBlockListPointer->push_front(entryStructPointer);
+            }
+            else  // Process a main block list entry.
+            {
+                // Prepare the filter list string.
+                prepareFilterListString(filterListString, entryStructPointer);
 
-                // Add the filter list entry struct to the main block list.
-                filterListStructPointer->mainBlockList.push_front(entryStructPointer);
+                // Add the entry struct to the main block list.
+                filterListStructPointer->mainBlockListPointer->push_front(entryStructPointer);
 
                 // Log the addition to the filter list.
                 //qDebug().noquote().nospace() << entryStructPointer->originalEntry << " added to Main Block List from " << filterListFileName << ".";
@@ -808,111 +1267,46 @@ void FilterListHelper::populateRequestStruct(RequestStruct *requestStructPointer
     requestStructPointer->dispositionInt = disposition;
     requestStructPointer->filterListTitle = filterListTitle;
     requestStructPointer->sublistInt = sublistInt;
-    requestStructPointer->entryStruct.appliedEntry = entryStructPointer->appliedEntry;
+    requestStructPointer->entryStruct.appliedEntryList = entryStructPointer->appliedEntryList;
     requestStructPointer->entryStruct.originalEntry = entryStructPointer->originalEntry;
 }
 
-bool FilterListHelper::processFilterOptions(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
-                                            EntryStruct *entryStructPointer) const
+void FilterListHelper::prepareFilterListString(QString &filterListString, EntryStruct *entryStructPointer) const
 {
-    // Block font requests.
-    if ((entryStructPointer->font == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeFontResource))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
-
-    // Block image requests.
-    if ((entryStructPointer->image == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeImage))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
-
-    // Block main frame requests.
-    if ((entryStructPointer->mainFrame == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) ||
-                                                                                    (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame)))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
-
-    // Block media requests.
-    if ((entryStructPointer->media == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeMedia))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
-
-    // Block object requests.
-    if ((entryStructPointer->object == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeObject))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
-
-    // Block other requests.
-    if ((entryStructPointer->other == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSubResource) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeWorker) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSharedWorker) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePrefetch) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeFavicon) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeServiceWorker) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeCspReport) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePluginResource) ||
-                                                                                (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeUnknown)))
+    // Check if this is an initial match.
+    if (filterListString.startsWith(QLatin1Char('|')))
     {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
+        // Strip the initial `|`.
+        filterListString.remove(0, 1);
 
-    // Block ping requests
-    if ((entryStructPointer->ping == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypePing))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+        // Set the initial match flag.
+        entryStructPointer->initialMatch = true;
     }
 
-    // Block script requests.
-    if ((entryStructPointer->script == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeScript))
+    // Check if this is a final match.
+    if (filterListString.endsWith(QLatin1Char('|')))
     {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
+        // Strip the final `|`.
+        filterListString.chop(1);
 
-    // Block style sheet requests.
-    if ((entryStructPointer->styleSheet == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeStylesheet))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
+        // Set the final match flag.
+        entryStructPointer->finalMatch = true;
     }
 
-    // Block sub resource requests.
-    if ((entryStructPointer->subFrame == FilterOptionEnum::Disposition::Apply) && ((requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeSubFrame) ||
-                                                                                   (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame)))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
+    // Remove the initial asterisk if it exists.
+    if (filterListString.startsWith(QLatin1Char('*')))
+        filterListString.remove(0, 1);
 
-    // Block XML HTTP requests.
-    if ((entryStructPointer->xmlHttpRequest == FilterOptionEnum::Disposition::Apply) && (requestStructPointer->resourceTypeInt == QWebEngineUrlRequestInfo::ResourceTypeXhr))
-    {
-        // Block the request.
-        return blockRequest(urlRequestInfo, requestStructPointer, filterListTitle, sublistInt, entryStructPointer);
-    }
+    // Remove the final asterisk if it exists.
+    if (filterListString.endsWith(QLatin1Char('*')))
+        filterListString.chop(1);
 
-    // Returning true continues processing the filter list.
-    return true;
-}
+    // Split the filter list string and set it as the applied entry list.
+    entryStructPointer->appliedEntryList = filterListString.split(QLatin1Char('*'));
 
-void FilterListHelper::removeInitialAndTrailingAsterisks(QString &filterListEntry) const
-{
-    // Remove the initial asterisk if it exists.
-    if (filterListEntry.startsWith(QLatin1Char('*')))
-        filterListEntry.remove(0, 1);
+    // Store the size of the applied entry list.
+    entryStructPointer->sizeOfAppliedEntryList = entryStructPointer->appliedEntryList.size();
 
-    // Remove the final asterisk if it exists.
-    if (filterListEntry.endsWith(QLatin1Char('*')))
-        filterListEntry.chop(1);
+    // Determine if this is a single applied entry (including an empty entry).
+    entryStructPointer->singleAppliedEntry = (entryStructPointer->sizeOfAppliedEntryList == 1);
 }
index f8bfdf1cc887810e37a6764c8f2b3b11b6fa2ada..772d86a7153682ea8881428ee6dfe8ac728663fa 100644 (file)
@@ -44,6 +44,7 @@ public:
     static const int MAIN_ALLOWLIST = 0;
     static const int MAIN_BLOCKLIST = 1;
     static const int INITIAL_DOMAIN_BLOCKLIST = 2;
+    static const int REGULAR_EXPRESSION_BLOCKLIST = 3;
 
     // The public variables.
     FilterListStruct *easyListStructPointer;
@@ -55,8 +56,8 @@ public:
     // The public functions.
     bool checkFilterLists(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer) const;
     QString getDispositionString(int dispositionInt) const;
-    QString getFilterOptionDispositionString(const FilterOptionEnum::Disposition filterOptionDisposition) const;
     QString getNavigationTypeString(int navigationTypeInt) const;
+    QString getRequestOptionDispositionString(const FilterOptionEnum::Disposition filterOptionDisposition) const;
     QString getResourceTypeString(int resourceTypeInt) const;
     QString getSublistName(int sublistInt) const;
 
@@ -107,16 +108,23 @@ private:
     QString MAIN_ALLOWLIST_STRING;
     QString MAIN_BLOCKLIST_STRING;
     QString INITIAL_DOMAIN_BLOCKLIST_STRING;
+    QString REGULAR_EXPRESSION_BLOCKLIST_STRING;
 
     // The private functions.
     bool blockRequest(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt, EntryStruct *entryStructPointer) const;
+    bool checkAppliedEntry(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+                           EntryStruct *entryStructPointer, QString &urlString, QString &urlStringWithSeparators) const;
+    bool checkDomain(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+                     EntryStruct *entryStructPointer) const;
     bool checkIndividualList(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, FilterListStruct *filterListStructPointer) const;
+    bool checkRegularExpression(QWebEngineUrlRequestInfo &urlRequestInfo, UrlStruct &urlStruct, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+                                EntryStruct *entryStructPointer) const;
+    bool checkRequestOptions(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
+                             EntryStruct *entryStructPointer) const;
     bool checkThirdParty(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const bool isThirdPartyRequest, const QString &filterListTitle, const int sublistInt,
                          EntryStruct *entryStructPointer) const;
     FilterListStruct* populateFilterList(const QString &filterListFileName) const;
     void populateRequestStruct(RequestStruct *requestStructPointer, const int disposition, const QString &filterListTitle, const int sublistInt, EntryStruct *entryStructPointer) const;
-    bool processFilterOptions(QWebEngineUrlRequestInfo &urlRequestInfo, RequestStruct *requestStructPointer, const QString &filterListTitle, const int sublistInt,
-                              EntryStruct *entryStructPointer) const;
-    void removeInitialAndTrailingAsterisks(QString &filterListEntry) const;
+    void prepareFilterListString(QString &filterListString, EntryStruct *entryStructPointer) const;
 };
 #endif
index 3b47e7e052d41066d4d23157982940bb9e89b5d4..18944ea5ae0587bb06940c9f2286bd7a4e6b7358 100644 (file)
@@ -45,10 +45,10 @@ void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &urlReques
     requestStructPointer->urlString = urlRequestInfo.requestUrl().toString();
 
     // Check the filter lists.
-    bool requestNotHandled = globalFilterListHelperPointer->checkFilterLists(urlRequestInfo, requestStructPointer);
+    bool continueProcessing = globalFilterListHelperPointer->checkFilterLists(urlRequestInfo, requestStructPointer);
 
     // Further process the request if it hasn't already been handled.
-    if (requestNotHandled) {
+    if (continueProcessing) {
         // Handle the request according to the resource type.
         switch (urlRequestInfo.resourceType())
         {
@@ -61,6 +61,9 @@ void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &urlReques
                 // Mark the request struct as blocked.
                 requestStructPointer->dispositionInt = FilterListHelper::BLOCKED;
 
+                // Mark the ping as blocked by the default behavior.
+                requestStructPointer->filterListTitle = i18nc("Default HTTP ping blocking", "Default blocking of all HTTP ping requests.");
+
                 // Display the HTTP Ping blocked dialog.
                 emit displayHttpPingDialog(urlRequestInfo.requestUrl().toString());
 
index 67a43eb391834d3c3fa02116bde9729c0e0f5a3e..3354a6a9e7ef4e70bb33f47c0ee68f6cf2261c64 100644 (file)
 #include "enums/FilterOptionEnum.h"
 
 // Qt toolkit headers.
-#include <QString>
+#include <QStringList>
 
 struct EntryStruct
 {
     // The strings.
-    QString appliedEntry;
-    QString filterOptions;
     QString originalEntry;
+    QString originalFilterOptions;
 
-    // The filter options flag.
-    bool hasFilterOptions = false;
+    // The string lists.
+    QStringList appliedEntryList;
+    QStringList appliedFilterOptionsList;
+    QStringList domainList;
+
+    // The booleans.
+    bool finalMatch = false;
+    bool hasRequestOptions = false;
+    bool initialMatch = false;
+    bool singleAppliedEntry = false;
+
+    // The ints.
+    int sizeOfAppliedEntryList;
 
     // The filter options.
+    FilterOptionEnum::Disposition domain = FilterOptionEnum::Disposition::Null;
     FilterOptionEnum::Disposition font = FilterOptionEnum::Disposition::Null;
     FilterOptionEnum::Disposition image = FilterOptionEnum::Disposition::Null;
     FilterOptionEnum::Disposition mainFrame = FilterOptionEnum::Disposition::Null;
index ef560d1485aedb53a4bb82c2a8d06edf67b506e5..e21606857a19cb34cbc6e8e3984aaa79e912fc43 100644 (file)
 
 struct FilterListStruct
 {
+    // The strings.
     QString title;
     QString version;
     QString filePath;
-    std::forward_list<EntryStruct *> mainAllowList;
-    std::forward_list<EntryStruct *> mainBlockList;
-    std::forward_list<EntryStruct *> initialDomainBlockList;
+
+    // The filter lists.
+    std::forward_list<EntryStruct *> *mainAllowListPointer = new std::forward_list<EntryStruct *>;
+    std::forward_list<EntryStruct *> *mainBlockListPointer = new std::forward_list<EntryStruct *>;
+    std::forward_list<EntryStruct *> *initialDomainBlockListPointer = new std::forward_list<EntryStruct *>;
+    std::forward_list<EntryStruct *> *regularExpressionBlockListPointer = new std::forward_list<EntryStruct *>;
 };
 #endif
index ea135d02195f3274562990a9f9b914d19c13b0ff..76a0371e76cde92c77886933ee051db11288625b 100644 (file)
@@ -29,6 +29,7 @@ struct UrlStruct
     QString urlStringWithSeparators;
     QString truncatedUrlString;
     QString truncatedUrlStringWithSeparators;
+    QString fqdn;
     bool isThirdPartyRequest;
 };
 #endif
diff --git a/src/uis/FilterEntryDialog.ui b/src/uis/FilterEntryDialog.ui
new file mode 100644 (file)
index 0000000..c465d16
--- /dev/null
@@ -0,0 +1,680 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Copyright 2024 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>FilterEntryDialog</class>
+
+    <widget class="QWidget">
+        <layout class="QVBoxLayout">
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Filter List. -->
+                    <item>
+                        <widget class="QLabel" name="filterListLabel">
+                            <property name="text">
+                                <string>Filter List</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="filterListLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Sublist. -->
+                    <item>
+                        <widget class="QLabel" name="sublistLabel">
+                            <property name="text">
+                                <string>Sublist</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="sublistListLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+
+            <!-- Applied Entry. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <item>
+                        <widget class="QLabel" name="appliedEntryListLabel">
+                            <property name="text">
+                                <string>Applied Entry List</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="appliedEntryListLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Domain. -->
+                    <item>
+                        <widget class="QLabel" name="domainLabel">
+                            <property name="text">
+                                <string>Domain</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="domainLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Third Party. -->
+                    <item>
+                        <widget class="QLabel" name="thirdPartyLabel">
+                            <property name="text">
+                                <string>Third Party</string>
+                            </property>
+
+                            <property name="alignment">
+                                <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="thirdPartyLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Initial Match. -->
+                    <item>
+                        <widget class="QLabel" name="initialMatchLabel">
+                            <property name="text">
+                                <string>Initial Match</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="initialMatchLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Final Match. -->
+                    <item>
+                        <widget class="QLabel" name="finalMatchLabel">
+                            <property name="text">
+                                <string>Final Match</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="finalMatchLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Domain List. -->
+                    <item>
+                        <widget class="QLabel" name="domainListLabel">
+                            <property name="text">
+                                <string>Domain List</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="domainListLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+
+            <item>
+                <!-- Request Options. -->
+                <widget class="QGroupBox">
+                    <!-- Has Request Options. -->
+                    <layout class="QVBoxLayout">
+                        <item>
+                            <layout class="QHBoxLayout">
+                                <item>
+                                    <spacer>
+                                        <property name="orientation">
+                                            <enum>Qt::Horizontal</enum>
+                                        </property>
+                                    </spacer>
+                                </item>
+
+                                <item>
+                                    <widget class="QCheckBox" name="hasRequestOptionsCheckBox">
+                                        <property name="text">
+                                            <string>Has Request Options</string>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item>
+                                    <spacer>
+                                        <property name="orientation">
+                                            <enum>Qt::Horizontal</enum>
+                                        </property>
+                                    </spacer>
+                                </item>
+                            </layout>
+                        </item>
+
+                        <item>
+                            <layout class="QGridLayout">
+                                <!-- Font. -->
+                                <item row="0" column="0">
+                                    <widget class="QLabel" name="fontLabel">
+                                        <property name="text">
+                                            <string>Font</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="0" column="1">
+                                    <widget class="QLineEdit" name="fontLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Image. -->
+                                <item row="0" column="2">
+                                    <widget class="QLabel" name="imageLabel">
+                                        <property name="text">
+                                            <string>Image</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="0" column="3">
+                                    <widget class="QLineEdit" name="imageLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Main Frame. -->
+                                <item row="0" column="4">
+                                    <widget class="QLabel" name="mainFrameLabel">
+                                        <property name="text">
+                                            <string>Main Frame</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="0" column="5">
+                                    <widget class="QLineEdit" name="mainFrameLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Media. -->
+                                <item row="0" column="6">
+                                    <widget class="QLabel" name="mediaLabel">
+                                        <property name="text">
+                                            <string>Media</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="0" column="7">
+                                    <widget class="QLineEdit" name="mediaLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Object. -->
+                                <item row="1" column="0">
+                                    <widget class="QLabel" name="objectLabel">
+                                        <property name="text">
+                                            <string>Object</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="1" column="1">
+                                    <widget class="QLineEdit" name="objectLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Other. -->
+                                <item row="1" column="2">
+                                    <widget class="QLabel" name="otherLabel">
+                                        <property name="text">
+                                            <string>Other</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="1" column="3">
+                                    <widget class="QLineEdit" name="otherLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Ping. -->
+                                <item row="1" column="4">
+                                    <widget class="QLabel" name="pingLabel">
+                                        <property name="text">
+                                            <string>Ping</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="1" column="5">
+                                    <widget class="QLineEdit" name="pingLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Script. -->
+                                <item row="1" column="6">
+                                    <widget class="QLabel" name="scriptLabel">
+                                        <property name="text">
+                                            <string>Script</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="1" column="7">
+                                    <widget class="QLineEdit" name="scriptLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Style Sheet. -->
+                                <item row="2" column="0">
+                                    <widget class="QLabel" name="styleSheetLabel">
+                                        <property name="text">
+                                            <string>Style Sheet</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="2" column="1">
+                                    <widget class="QLineEdit" name="styleSheetLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- Sub Frame. -->
+                                <item row="2" column="2">
+                                    <widget class="QLabel" name="subFrameLabel">
+                                        <property name="text">
+                                            <string>Sub Frame</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="2" column="3">
+                                    <widget class="QLineEdit" name="subFrameLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <!-- XML HTTP Request. -->
+                                <item row="2" column="4">
+                                    <widget class="QLabel" name="xmlHttpRequestLabel">
+                                        <property name="text">
+                                            <string>XML HTTP Request</string>
+                                        </property>
+
+                                        <property name="alignment">
+                                            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                                        </property>
+                                    </widget>
+                                </item>
+
+                                <item row="2" column="5">
+                                    <widget class="QLineEdit" name="xmlHttpRequestLineEdit">
+                                        <property name="readOnly">
+                                            <bool>true</bool>
+                                        </property>
+
+                                        <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                                        <property name="focusPolicy">
+                                            <enum>Qt::NoFocus</enum>
+                                        </property>
+                                    </widget>
+                                </item>
+                            </layout>
+                        </item>
+                    </layout>
+                </widget>
+            </item>
+
+            <!-- Applied Filter Options. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <item>
+                        <widget class="QLabel" name="appliedFilterOptionsLabel">
+                            <property name="text">
+                                <string>Applied Filter Options</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="appliedFilterOptionsLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+
+            <!-- Original Filter Options. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <item>
+                        <widget class="QLabel" name="originalFilterOptionsLabel">
+                            <property name="text">
+                                <string>Original Filter Options</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="originalFilterOptionsLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+
+            <!-- Original Entry. -->
+            <item>
+                <layout class="QHBoxLayout">
+                    <item>
+                        <widget class="QLabel" name="originalEntryLabel">
+                            <property name="text">
+                                <string>Original Entry</string>
+                            </property>
+                        </widget>
+                    </item>
+
+                    <item>
+                        <widget class="QLineEdit" name="originalEntryLineEdit">
+                            <property name="readOnly">
+                                <bool>true</bool>
+                            </property>
+
+                            <!-- Disabling focus allows the arrow keys to activate the buttons. -->
+                            <property name="focusPolicy">
+                                <enum>Qt::NoFocus</enum>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+
+            <!-- Spacer. -->
+            <item>
+                <spacer>
+                    <property name="orientation">
+                        <enum>Qt::Vertical</enum>
+                    </property>
+                </spacer>
+            </item>
+
+            <item>
+                <layout class="QHBoxLayout">
+                    <!-- Previous button.  -->
+                    <item>
+                        <widget class="QPushButton" name="previousButton">
+                            <property name="text">
+                                <string>Previous</string>
+                            </property>
+
+                            <property name="icon">
+                                <iconset theme="go-previous" />
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Next button.  -->
+                    <item>
+                        <widget class="QPushButton" name="nextButton">
+                            <property name="text">
+                                <string>Next</string>
+                            </property>
+
+                            <property name="icon">
+                                <iconset theme="go-next" />
+                            </property>
+                        </widget>
+                    </item>
+
+                    <!-- Close button - dialog button box. -->
+                    <item>
+                        <widget class="QDialogButtonBox" name="dialogButtonBox">
+                            <property name="standardButtons">
+                                <set>QDialogButtonBox::Close</set>
+                            </property>
+                        </widget>
+                    </item>
+                </layout>
+            </item>
+        </layout>
+    </widget>
+</ui>
index 899fe31a06bf518900b2e60f6a556486401076de..d0a471d54cccebbf8bbc2bfd10210dafe7324549 100644 (file)
             <item>
                 <layout class="QHBoxLayout">
                     <item>
-                        <widget class="QLabel" name="appliedEntryLabel">
+                        <widget class="QLabel" name="appliedEntryListLabel">
                             <property name="text">
-                                <string>Applied Entry</string>
+                                <string>Applied Entry List</string>
                             </property>
                         </widget>
                     </item>
 
                     <item>
-                        <widget class="QLineEdit" name="appliedEntryLineEdit">
+                        <widget class="QLineEdit" name="appliedEntryListLineEdit">
                             <property name="readOnly">
                                 <bool>true</bool>
                             </property>