/*
 * 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 "RequestDetailDialog.h"
#include "GlobalVariables.h"
#include "ui_RequestDetailDialog.h"

// KDE Frameworks headers.
#include <KActionCollection>
#include <KColorScheme>

// Qt toolkit headers.
#include <QShortcut>

// Construct the class.
RequestDetailDialog::RequestDetailDialog(QWidget *parentWidgetPointer, QTableWidget *tableWidgetPointer, const int initialRow) :
                                         QDialog(parentWidgetPointer), currentRow(initialRow), tableWidgetPointer(tableWidgetPointer)
{
    // Set the window modality.
    setWindowModality(Qt::WindowModality::ApplicationModal);

    // Instantiate the request detail dialog UI.
    Ui::RequestDetailDialog requestDetailDialogUi;

    // Setup the UI.
    requestDetailDialogUi.setupUi(this);

    // Get handles for the views.
    dispositionLineEditPointer = requestDetailDialogUi.dispositionLineEdit;
    webPageUrlLineEditPointer = requestDetailDialogUi.webPageUrlLineEdit;
    requestUrlLineEditPointer = requestDetailDialogUi.requestUrlLineEdit;
    requestUrlWithSeparatorsLineEditPointer = requestDetailDialogUi.requestUrlWithSeparatorsLineEdit;
    truncatedRequestUrlLineEditPointer = requestDetailDialogUi.truncatedRequestUrlLineEdit;
    truncatedRequestUrlWithSeparatorsLineEditPointer = requestDetailDialogUi.truncatedRequestUrlWithSeparatorsLineEdit;
    requestMethodLineEditPointer = requestDetailDialogUi.requestMethodLineEdit;
    navigationTypeLineEditPointer = requestDetailDialogUi.navigationTypeLineEdit;
    thirdPartyRequestLineEditPointer = requestDetailDialogUi.thirdPartyRequestLineEdit;
    resourceTypeLineEditPointer = requestDetailDialogUi.resourceTypeLineEdit;
    filterListEntryWidget = requestDetailDialogUi.filterListEntryWidget;
    filterListLineEditPointer = requestDetailDialogUi.filterListLineEdit;
    sublistLineEditPointer = requestDetailDialogUi.sublistListLineEdit;
    appliedEntryListLineEditPointer = requestDetailDialogUi.appliedEntryListLineEdit;
    domainLineEditPointer = requestDetailDialogUi.domainLineEdit;
    thirdPartyFilterLineEditPointer = requestDetailDialogUi.thirdPartyFilterLineEdit;
    initialMatchLineEditPointer = requestDetailDialogUi.initialMatchLineEdit;
    finalMatchLineEditPointer = requestDetailDialogUi.finalMatchLineEdit;
    domainListLineEditPointer = requestDetailDialogUi.domainListLineEdit;
    hasRequestOptionsCheckBoxPointer = requestDetailDialogUi.hasRequestOptionsCheckBox;
    fontLineEditPointer = requestDetailDialogUi.fontLineEdit;
    imageLineEditPointer = requestDetailDialogUi.imageLineEdit;
    mainFrameLineEditPointer = requestDetailDialogUi.mainFrameLineEdit;
    mediaLineEditPointer = requestDetailDialogUi.mediaLineEdit;
    objectLineEditPointer = requestDetailDialogUi.objectLineEdit;
    otherLineEditPointer = requestDetailDialogUi.otherLineEdit;
    pingLineEditPointer = requestDetailDialogUi.pingLineEdit;
    scriptLineEditPointer = requestDetailDialogUi.scriptLineEdit;
    styleSheetLineEditPointer = requestDetailDialogUi.styleSheetLineEdit;
    subFrameLineEditPointer = requestDetailDialogUi.subFrameLineEdit;
    xmlHttpRequestLineEditPointer = requestDetailDialogUi.xmlHttpRequestLineEdit;
    appliedFilterOptionsLineEditPointer = requestDetailDialogUi.appliedFilterOptionsLineEdit;
    originalFilterOptionsLineEditPointer = requestDetailDialogUi.originalFilterOptionsLineEdit;
    originalEntryLineEditPointer = requestDetailDialogUi.originalEntryLineEdit;
    previousButtonPointer = requestDetailDialogUi.previousButton;
    nextButtonPointer = requestDetailDialogUi.nextButton;
    QDialogButtonBox *dialogButtonBoxPointer = requestDetailDialogUi.dialogButtonBox;
    QPushButton *closeButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::StandardButton::Close);

    // 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 = dispositionLineEditPointer->palette();
    negativeBackgroundPalette = normalBackgroundPalette;
    positiveBackgroundPalette = normalBackgroundPalette;

    // Modify the palettes.
    KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
    KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);

    // 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 RequestDetailDialog::populateDialog(const int row)
{
    // Set the window title.
    setWindowTitle(i18nc("The request detail dialog window title", "Request %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);

    // Get the first table widget item in the row.
    QTableWidgetItem *rowFirstTableWidgetItemPointer = tableWidgetPointer->item(row, 0);

    // Get the data variant.
    QVariant dataVariant = rowFirstTableWidgetItemPointer->data(Qt::UserRole);

    // Get the request struct byte array from the data variant.
    QByteArray requestStructByteArray = dataVariant.toByteArray();

    // Determine if previous should be enabled.
    bool previousEnabled = (row > 0);

    // Determine if next should be enabled.
    bool nextEnabled = (row < (tableWidgetPointer->rowCount() - 1));

    // Create a request struct data stream reader.
    QDataStream requestStructDataStreamReader(requestStructByteArray);

    // Create a new request struct.
    RequestStruct *requestStructPointer = new RequestStruct();

    // Populate the new request struct.
    requestStructDataStreamReader >> requestStructPointer->dispositionInt;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.originalEntry;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.originalFilterOptions;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.appliedEntryList;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.appliedFilterOptionsList;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.domainList;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.finalMatch;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.hasRequestOptions;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.initialMatch;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.domain;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.font;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.image;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.mainFrame;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.media;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.object;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.other;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.ping;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.script;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.styleSheet;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.subFrame;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.thirdParty;
    requestStructDataStreamReader >> requestStructPointer->entryStruct.xmlHttpRequest;
    requestStructDataStreamReader >> requestStructPointer->filterListTitle;
    requestStructDataStreamReader >> requestStructPointer->isThirdPartyRequest;
    requestStructDataStreamReader >> requestStructPointer->matchedUrlType;
    requestStructDataStreamReader >> requestStructPointer->navigationTypeInt;
    requestStructDataStreamReader >> requestStructPointer->requestMethodString;
    requestStructDataStreamReader >> requestStructPointer->resourceTypeInt;
    requestStructDataStreamReader >> requestStructPointer->sublistInt;
    requestStructDataStreamReader >> requestStructPointer->truncatedUrlString;
    requestStructDataStreamReader >> requestStructPointer->truncatedUrlStringWithSeparators;
    requestStructDataStreamReader >> requestStructPointer->urlString;
    requestStructDataStreamReader >> requestStructPointer->urlStringWithSeparators;
    requestStructDataStreamReader >> requestStructPointer->webPageUrlString;

    // Make a local copy of the has request options boolean.
    bool hasRequestOptions = requestStructPointer->entryStruct.hasRequestOptions;

    // Populate the views.
    dispositionLineEditPointer->setText(globalFilterListHelperPointer->getDispositionString(requestStructPointer->dispositionInt));
    webPageUrlLineEditPointer->setText(requestStructPointer->webPageUrlString);
    requestUrlLineEditPointer->setText(requestStructPointer->urlString);
    requestUrlWithSeparatorsLineEditPointer->setText(requestStructPointer->urlStringWithSeparators);
    truncatedRequestUrlLineEditPointer->setText(requestStructPointer->truncatedUrlString);
    truncatedRequestUrlWithSeparatorsLineEditPointer->setText(requestStructPointer->truncatedUrlStringWithSeparators);
    requestMethodLineEditPointer->setText(requestStructPointer->requestMethodString);
    thirdPartyRequestLineEditPointer->setText(requestStructPointer->isThirdPartyRequest ? i18n("Yes") : QLatin1String());
    navigationTypeLineEditPointer->setText(globalFilterListHelperPointer->getNavigationTypeString(requestStructPointer->navigationTypeInt));
    resourceTypeLineEditPointer->setText(globalFilterListHelperPointer->getResourceTypeString(requestStructPointer->resourceTypeInt));
    filterListLineEditPointer->setText(requestStructPointer->filterListTitle);
    sublistLineEditPointer->setText(globalFilterListHelperPointer->getSublistName(requestStructPointer->sublistInt));
    appliedEntryListLineEditPointer->setText(requestStructPointer->entryStruct.appliedEntryList.join(QLatin1String(" * ")));
    domainLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.domain));
    thirdPartyFilterLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.thirdParty));
    initialMatchLineEditPointer->setText(requestStructPointer->entryStruct.initialMatch ? i18n("Yes") : QLatin1String());
    finalMatchLineEditPointer->setText(requestStructPointer->entryStruct.finalMatch ? i18n("Yes") : QLatin1String());
    domainListLineEditPointer->setText(requestStructPointer->entryStruct.domainList.join(QLatin1String(" | ")));
    hasRequestOptionsCheckBoxPointer->setChecked(hasRequestOptions);
    fontLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.font));
    imageLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.image));
    mainFrameLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.mainFrame));
    mediaLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.media));
    objectLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.object));
    otherLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.other));
    pingLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.ping));
    scriptLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.script));
    styleSheetLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.styleSheet));
    subFrameLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.subFrame));
    xmlHttpRequestLineEditPointer->setText(globalFilterListHelperPointer->getRequestOptionDispositionString(requestStructPointer->entryStruct.xmlHttpRequest));
    appliedFilterOptionsLineEditPointer->setText(requestStructPointer->entryStruct.appliedFilterOptionsList.join(QLatin1String(" , ")));
    originalFilterOptionsLineEditPointer->setText(requestStructPointer->entryStruct.originalFilterOptions);
    originalEntryLineEditPointer->setText(requestStructPointer->entryStruct.originalEntry);

    // Determine if this is an allow list, which have a sublist int of of 0-2.
    isAllowList = (requestStructPointer->sublistInt <= 2);

    // Set the third-party request background palette.
    if (requestStructPointer->isThirdPartyRequest)
        thirdPartyRequestLineEditPointer->setPalette(negativeBackgroundPalette);
    else
        thirdPartyRequestLineEditPointer->setPalette(normalBackgroundPalette);

    // Set the initial and final background palettes.
    setInitialOrFinalBackgroundPalette(initialMatchLineEditPointer);
    setInitialOrFinalBackgroundPalette(finalMatchLineEditPointer);

    // Set the request option background palettes.
    setFilterOptionBackgroundPalette(domainLineEditPointer);
    setFilterOptionBackgroundPalette(thirdPartyFilterLineEditPointer);
    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(hasRequestOptions);
    imageLineEditPointer->setEnabled(hasRequestOptions);
    mainFrameLineEditPointer->setEnabled(hasRequestOptions);
    mediaLineEditPointer->setEnabled(hasRequestOptions);
    objectLineEditPointer->setEnabled(hasRequestOptions);
    otherLineEditPointer->setEnabled(hasRequestOptions);
    pingLineEditPointer->setEnabled(hasRequestOptions);
    scriptLineEditPointer->setEnabled(hasRequestOptions);
    styleSheetLineEditPointer->setEnabled(hasRequestOptions);
    subFrameLineEditPointer->setEnabled(hasRequestOptions);
    xmlHttpRequestLineEditPointer->setEnabled(hasRequestOptions);

    // 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);

    // Set the sublist background palette.
    switch (requestStructPointer->sublistInt)
    {
        case FilterListHelper::MAIN_ALLOWLIST:
        case FilterListHelper::INITIAL_DOMAIN_ALLOWLIST:
        case FilterListHelper::REGULAR_EXPRESSION_ALLOWLIST:
            sublistLineEditPointer->setPalette(positiveBackgroundPalette);
            break;

        case FilterListHelper::MAIN_BLOCKLIST:
        case FilterListHelper::INITIAL_DOMAIN_BLOCKLIST:
        case FilterListHelper::REGULAR_EXPRESSION_BLOCKLIST:
            sublistLineEditPointer->setPalette(negativeBackgroundPalette);
            break;
    }

    // Set the applied entry background palette to be the same as the sublist.
    appliedEntryListLineEditPointer->setPalette(sublistLineEditPointer->palette());

    // Set the resource type background palette.
    if (hasRequestOptions)  // There are request options.
    {
        switch (requestStructPointer->resourceTypeInt)
        {
            // Font
            case QWebEngineUrlRequestInfo::ResourceTypeFontResource:
            {
                resourceTypeLineEditPointer->setPalette(fontLineEditPointer->palette());
                break;
            }

            // Image.
            case QWebEngineUrlRequestInfo::ResourceTypeImage:
            {
                resourceTypeLineEditPointer->setPalette(imageLineEditPointer->palette());
                break;
            }

            // Main Frame.
            case QWebEngineUrlRequestInfo::ResourceTypeMainFrame:
            case QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame:
            {
                resourceTypeLineEditPointer->setPalette(mainFrameLineEditPointer->palette());
                break;
            }

            // Media.
            case QWebEngineUrlRequestInfo::ResourceTypeMedia:
            {
                resourceTypeLineEditPointer->setPalette(mediaLineEditPointer->palette());
                break;
            }

            // Object.
            case QWebEngineUrlRequestInfo::ResourceTypeObject:
            {
                resourceTypeLineEditPointer->setPalette(objectLineEditPointer->palette());
                break;
            }

            // Other.
            case QWebEngineUrlRequestInfo::ResourceTypeSubResource:
            case QWebEngineUrlRequestInfo::ResourceTypeWorker:
            case QWebEngineUrlRequestInfo::ResourceTypeSharedWorker:
            case QWebEngineUrlRequestInfo::ResourceTypePrefetch:
            case QWebEngineUrlRequestInfo::ResourceTypeFavicon:
            case QWebEngineUrlRequestInfo::ResourceTypeServiceWorker:
            case QWebEngineUrlRequestInfo::ResourceTypeCspReport:
            case QWebEngineUrlRequestInfo::ResourceTypePluginResource:
            case QWebEngineUrlRequestInfo::ResourceTypeUnknown:
            {
                resourceTypeLineEditPointer->setPalette(otherLineEditPointer->palette());
                break;
            }

            // Ping.
            case QWebEngineUrlRequestInfo::ResourceTypePing:
            {
                resourceTypeLineEditPointer->setPalette(pingLineEditPointer->palette());
                break;
            }

            // Script.
            case QWebEngineUrlRequestInfo::ResourceTypeScript:
            {
                resourceTypeLineEditPointer->setPalette(scriptLineEditPointer->palette());
                break;
            }

            // Style Sheet.
            case QWebEngineUrlRequestInfo::ResourceTypeStylesheet:
            {
                resourceTypeLineEditPointer->setPalette(styleSheetLineEditPointer->palette());
                break;
            }

            // Sub Frame.
            case QWebEngineUrlRequestInfo::ResourceTypeSubFrame:
            case QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame:
            {
                resourceTypeLineEditPointer->setPalette(subFrameLineEditPointer->palette());
                break;
            }

            // XML HTTP Request.
            case QWebEngineUrlRequestInfo::ResourceTypeXhr:
            {
                resourceTypeLineEditPointer->setPalette(xmlHttpRequestLineEditPointer->palette());
                break;
            }
        }
    }
    else  // There are no request options.
    {
        // Reset the resource type background palette.
        resourceTypeLineEditPointer->setPalette(normalBackgroundPalette);
    }

    // Modify the interface based on the disposition.
    switch (requestStructPointer->dispositionInt)
    {
        case FilterListHelper::DEFAULT:
        {
            // Reset the disposition line edit background.
            dispositionLineEditPointer->setPalette(normalBackgroundPalette);

            // Reset the request URL palettes.
            requestUrlLineEditPointer->setPalette(normalBackgroundPalette);
            requestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);

            // Hide the filter list entry views.
            filterListEntryWidget->hide();

            break;
        }

        case FilterListHelper::ALLOWED:
        {
            // Colorize the disposition line edit background.
            dispositionLineEditPointer->setPalette(positiveBackgroundPalette);

            // Colorize the request URLs.
            setRequestUrlBackgroundPalettes(requestStructPointer->matchedUrlType);

            // Show the filter list entry views.
            filterListEntryWidget->show();

            break;
        }

        case FilterListHelper::BLOCKED:
        {
            // Colorize the disposition line edit background.
            dispositionLineEditPointer->setPalette(negativeBackgroundPalette);

            // Colorize the request URLs.
            setRequestUrlBackgroundPalettes(requestStructPointer->matchedUrlType);

            // Show the filter list entry views.
            filterListEntryWidget->show();

            break;
        }
    }
}

void RequestDetailDialog::previous()
{
    // Update the current row.
    --currentRow;

    // Populate the dialog.
    populateDialog(currentRow);
}

void RequestDetailDialog::next()
{
    // Update the current row.
    ++currentRow;

    // Populate the dialog.
    populateDialog(currentRow);
}

void RequestDetailDialog::setFilterOptionBackgroundPalette(QLineEdit *lineEditPointer)
{
    // Set the background palette according to the text.
    if (lineEditPointer->text() == globalFilterListHelperPointer->getRequestOptionDispositionString(FilterOptionDisposition::Null))  // Not text is displayed.
    {
        // Set the normal background palette.
        lineEditPointer->setPalette(normalBackgroundPalette);
    }
    else if (lineEditPointer->text() == globalFilterListHelperPointer->getRequestOptionDispositionString(FilterOptionDisposition::Apply))  // `Apply` is displayed.
    {
        // Set the background palette according to the sublist type.
        if (isAllowList)
            lineEditPointer->setPalette(positiveBackgroundPalette);
        else
            lineEditPointer->setPalette(negativeBackgroundPalette);
    }
    else  // `Override` is displayed.
    {
        // Set the background palette according to the sublist type.
        if (isAllowList)
            lineEditPointer->setPalette(negativeBackgroundPalette);
        else
            lineEditPointer->setPalette(positiveBackgroundPalette);
    }
}

void RequestDetailDialog::setInitialOrFinalBackgroundPalette(QLineEdit *lineEditPointer)
{
    // Set the background palette according to the text.
    if (lineEditPointer->text() == i18n("Yes"))  // `Yes` is displayed.
    {
        // Set the background palette according to the sublist type.
        if (isAllowList)
            lineEditPointer->setPalette(positiveBackgroundPalette);
        else
            lineEditPointer->setPalette(negativeBackgroundPalette);
    }
    else  // No text is displayed.
    {
        // Set the normal background palette.
        lineEditPointer->setPalette(normalBackgroundPalette);
    }
}

void RequestDetailDialog::setRequestUrlBackgroundPalettes(RequestUrlType matchedUrlType)
{
    // Colorize the request URL strings according to the matched URL.
    switch (matchedUrlType)
    {
        case RequestUrlType::Url:  // URL.
        {
            // Set the request URL palette to match the disposition line edit.
            requestUrlLineEditPointer->setPalette(dispositionLineEditPointer->palette());

            // Reset the other palettes.
            requestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);

            break;
        }

        case RequestUrlType::UrlWithSeparators:  // URL with separators.
        {
            // Set the request URL with separators palette to match the disposition line edit.
            requestUrlWithSeparatorsLineEditPointer->setPalette(dispositionLineEditPointer->palette());

            // Reset the other palettes.
            requestUrlLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);

            break;
        }

        case RequestUrlType::TruncatedUrl:  // Truncated URL.
        {
            // Set the truncated request URL palette to match the disposition line edit.
            truncatedRequestUrlLineEditPointer->setPalette(dispositionLineEditPointer->palette());

            // Reset the other palettes.
            requestUrlLineEditPointer->setPalette(normalBackgroundPalette);
            requestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);

            break;
        }

        case RequestUrlType::TruncatedUrlWithSeparators:  // Truncated URL with separators.
        {
            // Set the truncated request URL with separators palette to match the disposition line edit.
            truncatedRequestUrlWithSeparatorsLineEditPointer->setPalette(dispositionLineEditPointer->palette());

            // Reset the other palettes.
            requestUrlLineEditPointer->setPalette(normalBackgroundPalette);
            requestUrlWithSeparatorsLineEditPointer->setPalette(normalBackgroundPalette);
            truncatedRequestUrlLineEditPointer->setPalette(normalBackgroundPalette);

            break;
        }
    }
}
