1 /* SPDX-License-Identifier: GPL-3.0-or-later
2 * SPDX-FileCopyrightText: 2024-2025 Soren Stoutner <soren@stoutner.com>
4 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc/>.
6 * This program is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <https://www.gnu.org/licenses/>.
20 // Application headers.
21 #include "FilterListsDialog.h"
22 #include "GlobalVariables.h"
23 #include "ui_FilterListsDialog.h"
24 #include "dialogs/FilterEntryDialog.h"
26 // Qt toolkit headers.
29 #include <QTextStream>
31 // Construct the class.
32 FilterListsDialog::FilterListsDialog(QWidget *parentWidgetPointer) : QDialog(parentWidgetPointer)
34 // Set the window title.
35 setWindowTitle(i18nc("The filter lists dialog window title", "Filter Lists"));
37 // Set the window modality.
38 setWindowModality(Qt::WindowModality::ApplicationModal);
40 // Instantiate the filter lists dialog UI.
41 Ui::FilterListsDialog filterListsDialogUi;
44 filterListsDialogUi.setupUi(this);
46 // Get handles for the views.
47 filterListComboBoxPointer = filterListsDialogUi.filterListComboBox;
48 filterListTextEditPointer = filterListsDialogUi.filterListTextEdit;
49 sublistComboBoxPointer = filterListsDialogUi.sublistComboBox;
50 sublistTableWidgetPointer = filterListsDialogUi.sublistTableWidget;
51 QDialogButtonBox *dialogButtonBoxPointer = filterListsDialogUi.dialogButtonBox;
53 // Select an entire row at a time.
54 sublistTableWidgetPointer->setSelectionBehavior(QAbstractItemView::SelectRows);
56 // Open the filter entry dialog when a cell is clicked.
57 connect(sublistTableWidgetPointer, SIGNAL(cellClicked(int, int)), this, SLOT(showFilterEntryDialog(int)));
59 // Connect the combo boxes.
60 connect(filterListComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(populateFilterListTextEdit(int)));
61 connect(sublistComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(populateTableWidget(int)));
63 // Connect the buttons.
64 connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(close()));
66 // Populate the filter list combo box.
67 populateFilterListComboBox(globalFilterListHelperPointer->ultraPrivacyStructPointer);
68 populateFilterListComboBox(globalFilterListHelperPointer->ultraListStructPointer);
69 populateFilterListComboBox(globalFilterListHelperPointer->easyPrivacyStructPointer);
70 populateFilterListComboBox(globalFilterListHelperPointer->easyListStructPointer);
71 populateFilterListComboBox(globalFilterListHelperPointer->fanboyAnnoyanceStructPointer);
74 std::forward_list<EntryStruct *>* FilterListsDialog::getFilterListForwardList(FilterListStruct *filterListStructPointer) const
76 // Return the filter list forward list.
77 switch (sublistComboBoxPointer->currentIndex())
79 case FilterListHelper::MAIN_ALLOWLIST: return filterListStructPointer->mainAllowListPointer; // The main allow list.
80 case FilterListHelper::INITIAL_DOMAIN_ALLOWLIST: return filterListStructPointer->initialDomainAllowListPointer; // The initial domain allow list.
81 case FilterListHelper::REGULAR_EXPRESSION_ALLOWLIST: return filterListStructPointer->regularExpressionAllowListPointer; // The regular expression allow list.
82 case FilterListHelper::MAIN_BLOCKLIST: return filterListStructPointer->mainBlockListPointer; // The main block list.
83 case FilterListHelper::INITIAL_DOMAIN_BLOCKLIST: return filterListStructPointer->initialDomainBlockListPointer; // The initial domain block list.
84 case FilterListHelper::REGULAR_EXPRESSION_BLOCKLIST: return filterListStructPointer->regularExpressionBlockListPointer; // The regular expression block list.
87 // This return statement should never be reached.
88 return new std::forward_list<EntryStruct *>;
91 FilterListStruct *FilterListsDialog::getFilterListStruct(int filterListComboBoxIndex) const
93 // Return the filer list struct.
94 switch (filterListComboBoxIndex)
96 case 0: return globalFilterListHelperPointer->ultraPrivacyStructPointer; // UltraPrivacy.
97 case 1: return globalFilterListHelperPointer->ultraListStructPointer; // UltraList.
98 case 2: return globalFilterListHelperPointer->easyPrivacyStructPointer; // EasyPrivacy.
99 case 3: return globalFilterListHelperPointer->easyListStructPointer; // EasyList.
100 case 4: return globalFilterListHelperPointer->fanboyAnnoyanceStructPointer; // Fanboy's Annoyance List.
103 // This return statement should never be reached.
104 return new FilterListStruct;
107 void FilterListsDialog::populateFilterListComboBox(const FilterListStruct *filterListStructPointer) const
109 // Populate the filter list combo box.
110 filterListComboBoxPointer->addItem(i18nc("Filter list combo box items", "%1 - %2", filterListStructPointer->title, filterListStructPointer->version));
113 void FilterListsDialog::populateFilterListTextEdit(int filterListComboBoxIndex) const
115 // Get the filter list struct.
116 FilterListStruct *filterListStructPointer = getFilterListStruct(filterListComboBoxIndex);
118 // Get the filter list file.
119 QFile filterListFile(filterListStructPointer->filePath);
121 // Open the filter list file.
122 filterListFile.open(QIODevice::ReadOnly);
124 // Create a filter list text stream.
125 QTextStream filterListTextStream(&filterListFile);
127 // Populate the text edit.
128 filterListTextEditPointer->setText(filterListTextStream.readAll());
130 // Clear the sublist combo box.
131 sublistComboBoxPointer->clear();
133 // Calculate the size of the filter lists.
134 int mainAllowListSize = distance(filterListStructPointer->mainAllowListPointer->begin(), filterListStructPointer->mainAllowListPointer->end());
135 int initialDomainAllowListSize = distance(filterListStructPointer->initialDomainAllowListPointer->begin(), filterListStructPointer->initialDomainAllowListPointer->end());
136 int regularExpressionAllowListSize = distance(filterListStructPointer->regularExpressionAllowListPointer->begin(), filterListStructPointer->regularExpressionAllowListPointer->end());
137 int mainBlockListSize = distance(filterListStructPointer->mainBlockListPointer->begin(), filterListStructPointer->mainBlockListPointer->end());
138 int initialDomainBlockListSize = distance(filterListStructPointer->initialDomainBlockListPointer->begin(), filterListStructPointer->initialDomainBlockListPointer->end());
139 int regularExpressionBlockListSize = distance(filterListStructPointer->regularExpressionBlockListPointer->begin(), filterListStructPointer->regularExpressionBlockListPointer->end());
141 // Get the translated filter list names.
142 QString mainAllowListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::MAIN_ALLOWLIST);
143 QString initialDomainAllowListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::INITIAL_DOMAIN_ALLOWLIST);
144 QString regularExpressionAllowListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::REGULAR_EXPRESSION_ALLOWLIST);
145 QString mainBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::MAIN_BLOCKLIST);
146 QString initialDomainBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::INITIAL_DOMAIN_BLOCKLIST);
147 QString regularExpressionBlockListName = globalFilterListHelperPointer->getSublistName(FilterListHelper::REGULAR_EXPRESSION_BLOCKLIST);
149 // Populate the sublist combo box.
150 sublistComboBoxPointer->addItem(i18nc("The main allow list", "%1 - %2", mainAllowListName, mainAllowListSize));
151 sublistComboBoxPointer->addItem(i18nc("The initial domain allow list", "%1 - %2", initialDomainAllowListName, initialDomainAllowListSize));
152 sublistComboBoxPointer->addItem(i18nc("The regular expression allow list", "%1 - %2", regularExpressionAllowListName, regularExpressionAllowListSize));
153 sublistComboBoxPointer->addItem(i18nc("The main block list", "%1 - %2", mainBlockListName, mainBlockListSize));
154 sublistComboBoxPointer->addItem(i18nc("The initial domain block list", "%1 - %2", initialDomainBlockListName, initialDomainBlockListSize));
155 sublistComboBoxPointer->addItem(i18nc("the regular expression block list", "%1 - %2", regularExpressionBlockListName, regularExpressionBlockListSize));
158 void FilterListsDialog::populateTableWidget(int sublistComboBoxIndex) const
160 // Populate the table widget if there is at least one item in teh sublist combo box.
161 if (sublistComboBoxIndex >= 0)
163 // Wipe the current table.
164 sublistTableWidgetPointer->clear();
165 sublistTableWidgetPointer->setColumnCount(0);
166 sublistTableWidgetPointer->setRowCount(0);
168 // Get the filter list struct.
169 FilterListStruct *filterListStructPointer = getFilterListStruct(filterListComboBoxPointer->currentIndex());
171 // Create a filter list forward list.
172 std::forward_list<EntryStruct *> *filterListForwardListPointer;
174 // Populate the filter list forward list.
175 switch (sublistComboBoxIndex)
177 case FilterListHelper::MAIN_ALLOWLIST: // The main allow list.
178 filterListForwardListPointer = filterListStructPointer->mainAllowListPointer;
181 case FilterListHelper::INITIAL_DOMAIN_ALLOWLIST: // The initial domain allow list.
182 filterListForwardListPointer = filterListStructPointer->initialDomainAllowListPointer;
185 case FilterListHelper::REGULAR_EXPRESSION_ALLOWLIST: // The regular expression allow list.
186 filterListForwardListPointer = filterListStructPointer->regularExpressionAllowListPointer;
189 case FilterListHelper::MAIN_BLOCKLIST: // The main block list.
190 filterListForwardListPointer = filterListStructPointer->mainBlockListPointer;
193 case FilterListHelper::INITIAL_DOMAIN_BLOCKLIST: // The initial domain block list.
194 filterListForwardListPointer = filterListStructPointer->initialDomainBlockListPointer;
197 case FilterListHelper::REGULAR_EXPRESSION_BLOCKLIST: // the regular expression block list.
198 filterListForwardListPointer = filterListStructPointer->regularExpressionBlockListPointer;
202 // Create the columns.
203 sublistTableWidgetPointer->setColumnCount(22);
205 // Create the table headers.
206 QTableWidgetItem *appliedEntryListHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist applied entry list header", "Applied Entry List"));
207 QTableWidgetItem *initialMatchHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist initial match header", "Initial Match"));
208 QTableWidgetItem *finalMatchHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist final match header", "Final Match"));
209 QTableWidgetItem *domainHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist domain header", "Domain"));
210 QTableWidgetItem *domainListHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist domain list Header", "Domain List"));
211 QTableWidgetItem *thirdPartyHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist third-party header", "Third Party"));
212 QTableWidgetItem *hasRequestOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist has request options header", "Has Request Options"));
213 QTableWidgetItem *fontHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist font header", "Font"));
214 QTableWidgetItem *imageHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist image header", "Image"));
215 QTableWidgetItem *mainFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist main frame header", "Main Frame"));
216 QTableWidgetItem *mediaHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist media header", "Media"));
217 QTableWidgetItem *objectHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Object"));
218 QTableWidgetItem *otherHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist object header", "Other"));
219 QTableWidgetItem *pingHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist ping header", "Ping"));
220 QTableWidgetItem *scriptHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist script header", "Script"));
221 QTableWidgetItem *styleSheetHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist style sheet header", "Style Sheet"));
222 QTableWidgetItem *subFrameHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist sub frame header", "Sub Frame"));
223 QTableWidgetItem *webSocketHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist web socket header", "Web Socket"));
224 QTableWidgetItem *xmlHttpRequestHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist XML HTTP request header", "XML HTTP Request"));
225 QTableWidgetItem *appliedFilterOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist applied filter options header", "Applied Filter Options"));
226 QTableWidgetItem *originalFilterOptionsHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist original filter options header", "Original Filter Options"));
227 QTableWidgetItem *originalEntryHeaderItemPointer = new QTableWidgetItem(i18nc("Sublist original entry header", "Original Entry"));
229 // Set the horizontal headers.
230 sublistTableWidgetPointer->setHorizontalHeaderItem(0, appliedEntryListHeaderItemPointer);
231 sublistTableWidgetPointer->setHorizontalHeaderItem(1, initialMatchHeaderItemPointer);
232 sublistTableWidgetPointer->setHorizontalHeaderItem(2, finalMatchHeaderItemPointer);
233 sublistTableWidgetPointer->setHorizontalHeaderItem(3, domainHeaderItemPointer);
234 sublistTableWidgetPointer->setHorizontalHeaderItem(4, domainListHeaderItemPointer);
235 sublistTableWidgetPointer->setHorizontalHeaderItem(5, thirdPartyHeaderItemPointer);
236 sublistTableWidgetPointer->setHorizontalHeaderItem(6, hasRequestOptionsHeaderItemPointer);
237 sublistTableWidgetPointer->setHorizontalHeaderItem(7, fontHeaderItemPointer);
238 sublistTableWidgetPointer->setHorizontalHeaderItem(8, imageHeaderItemPointer);
239 sublistTableWidgetPointer->setHorizontalHeaderItem(9, mainFrameHeaderItemPointer);
240 sublistTableWidgetPointer->setHorizontalHeaderItem(10, mediaHeaderItemPointer);
241 sublistTableWidgetPointer->setHorizontalHeaderItem(11, objectHeaderItemPointer);
242 sublistTableWidgetPointer->setHorizontalHeaderItem(12, otherHeaderItemPointer);
243 sublistTableWidgetPointer->setHorizontalHeaderItem(13, pingHeaderItemPointer);
244 sublistTableWidgetPointer->setHorizontalHeaderItem(14, scriptHeaderItemPointer);
245 sublistTableWidgetPointer->setHorizontalHeaderItem(15, styleSheetHeaderItemPointer);
246 sublistTableWidgetPointer->setHorizontalHeaderItem(16, subFrameHeaderItemPointer);
247 sublistTableWidgetPointer->setHorizontalHeaderItem(17, webSocketHeaderItemPointer);
248 sublistTableWidgetPointer->setHorizontalHeaderItem(18, xmlHttpRequestHeaderItemPointer);
249 sublistTableWidgetPointer->setHorizontalHeaderItem(19, appliedFilterOptionsHeaderItemPointer);
250 sublistTableWidgetPointer->setHorizontalHeaderItem(20, originalFilterOptionsHeaderItemPointer);
251 sublistTableWidgetPointer->setHorizontalHeaderItem(21, originalEntryHeaderItemPointer);
253 // Initialize the row counter.
256 // Populate the table.
257 for (auto filterListEntry = filterListForwardListPointer->begin(); filterListEntry != filterListForwardListPointer->end(); ++filterListEntry) {
258 // Get the entry struct.
259 EntryStruct *entryStructPointer = *filterListEntry;
262 sublistTableWidgetPointer->insertRow(rowCounter);
264 // Create the entry items.
265 QTableWidgetItem *appliedEntryListItemPointer = new QTableWidgetItem(entryStructPointer->appliedEntryList.join(QLatin1String(" * ")));
266 QTableWidgetItem *initialMatchItemPointer = new QTableWidgetItem(entryStructPointer->initialMatch ? i18n("Yes") : QLatin1String());
267 QTableWidgetItem *finalMatchItemPointer = new QTableWidgetItem(entryStructPointer->finalMatch ? i18n("Yes") : QLatin1String());
268 QTableWidgetItem *domainItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->domain));
269 QTableWidgetItem *domainListItemPointer = new QTableWidgetItem(entryStructPointer->domainList.join(QLatin1String(" | ")));
270 QTableWidgetItem *thirdPartyItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->thirdParty));
271 QTableWidgetItem *hasRequestOptionsItemPointer = new QTableWidgetItem(entryStructPointer->hasRequestOptions ? i18n("Yes") : QLatin1String());
272 QTableWidgetItem *fontItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->font));
273 QTableWidgetItem *imageItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->image));
274 QTableWidgetItem *mainFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->mainFrame));
275 QTableWidgetItem *mediaItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->media));
276 QTableWidgetItem *objectItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->object));
277 QTableWidgetItem *otherItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->other));
278 QTableWidgetItem *pingItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->ping));
279 QTableWidgetItem *scriptItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->script));
280 QTableWidgetItem *styleSheetItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->styleSheet));
281 QTableWidgetItem *subFrameItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->subFrame));
282 QTableWidgetItem *webSocketItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->webSocket));
283 QTableWidgetItem *xmlHttpRequestItemPointer = new QTableWidgetItem(globalFilterListHelperPointer->getRequestOptionDispositionString(entryStructPointer->xmlHttpRequest));
284 QTableWidgetItem *appliedFilterOptionsItemPointer = new QTableWidgetItem(entryStructPointer->appliedFilterOptionsList.join(QLatin1String(" , ")));
285 QTableWidgetItem *originalFilterOptionsItemPointer = new QTableWidgetItem(entryStructPointer->originalFilterOptions);
286 QTableWidgetItem *originalEntryItemPointer = new QTableWidgetItem(entryStructPointer->originalEntry);
288 // Add the entries to the table.
289 sublistTableWidgetPointer->setItem(rowCounter, 0, appliedEntryListItemPointer);
290 sublistTableWidgetPointer->setItem(rowCounter, 1, initialMatchItemPointer);
291 sublistTableWidgetPointer->setItem(rowCounter, 2, finalMatchItemPointer);
292 sublistTableWidgetPointer->setItem(rowCounter, 3, domainItemPointer);
293 sublistTableWidgetPointer->setItem(rowCounter, 4, domainListItemPointer);
294 sublistTableWidgetPointer->setItem(rowCounter, 5, thirdPartyItemPointer);
295 sublistTableWidgetPointer->setItem(rowCounter, 6, hasRequestOptionsItemPointer);
296 sublistTableWidgetPointer->setItem(rowCounter, 7, fontItemPointer);
297 sublistTableWidgetPointer->setItem(rowCounter, 8, imageItemPointer);
298 sublistTableWidgetPointer->setItem(rowCounter, 9, mainFrameItemPointer);
299 sublistTableWidgetPointer->setItem(rowCounter, 10, mediaItemPointer);
300 sublistTableWidgetPointer->setItem(rowCounter, 11, objectItemPointer);
301 sublistTableWidgetPointer->setItem(rowCounter, 12, otherItemPointer);
302 sublistTableWidgetPointer->setItem(rowCounter, 13, pingItemPointer);
303 sublistTableWidgetPointer->setItem(rowCounter, 14, scriptItemPointer);
304 sublistTableWidgetPointer->setItem(rowCounter, 15, styleSheetItemPointer);
305 sublistTableWidgetPointer->setItem(rowCounter, 16, subFrameItemPointer);
306 sublistTableWidgetPointer->setItem(rowCounter, 17, webSocketItemPointer);
307 sublistTableWidgetPointer->setItem(rowCounter, 18, xmlHttpRequestItemPointer);
308 sublistTableWidgetPointer->setItem(rowCounter, 19, appliedFilterOptionsItemPointer);
309 sublistTableWidgetPointer->setItem(rowCounter, 20, originalFilterOptionsItemPointer);
310 sublistTableWidgetPointer->setItem(rowCounter, 21, originalEntryItemPointer);
312 // Increment the row counter.
316 // Get the table header view.
317 QHeaderView *headerViewPointer = sublistTableWidgetPointer->horizontalHeader();
319 // Resize the header to fit the contents.
320 headerViewPointer->resizeSections(QHeaderView::ResizeToContents);
322 // Connect changes in the sort order.
323 connect(headerViewPointer, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(sortTable(int, Qt::SortOrder)));
327 void FilterListsDialog::showFilterEntryDialog(int row)
329 // Get the filter list struct.
330 FilterListStruct *filterListStructPointer = getFilterListStruct(filterListComboBoxPointer->currentIndex());
332 // Get the sublist combo box index.
333 int sublistComboBoxIndex = sublistComboBoxPointer->currentIndex();
335 // Create a sublist title.
336 QString sublistTitle = globalFilterListHelperPointer->getSublistName(sublistComboBoxIndex);
338 // Determine if this is an allow list (which have indexes of 0-2).
339 bool isAllowList = (sublistComboBoxIndex <= 2);
341 // Instantiate the filter entry dialog.
342 FilterEntryDialog *filterEntryDialogPointer = new FilterEntryDialog(this, sublistTableWidgetPointer, row, filterListStructPointer->title, sublistTitle, isAllowList);
345 filterEntryDialogPointer->show();
348 void FilterListsDialog::sortTable(int column, Qt::SortOrder sortOrder) const
351 sublistTableWidgetPointer->sortItems(column, sortOrder);