]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/dialogs/DomainSettingsDialog.cpp
Add a default folder icon to the edit folder dialog. https://redmine.stoutner.com...
[PrivacyBrowserPC.git] / src / dialogs / DomainSettingsDialog.cpp
1 /*
2  * Copyright 2022-2024 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
5  *
6  * Privacy Browser PC is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser PC is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
18  // */
19
20 // Application headers.
21 #include "DomainSettingsDialog.h"
22 #include "Settings.h"
23 #include "ui_DomainSettingsDialog.h"
24 #include "databases/DomainsDatabase.h"
25
26 // Qt toolkit headers.
27 #include <QInputDialog>
28 #include <QMessageBox>
29 #include <QPushButton>
30 #include <QTimer>
31
32 // Define the public static int constants.
33 const int DomainSettingsDialog::SHOW_ALL_DOMAINS = 0;
34 const int DomainSettingsDialog::EDIT_DOMAIN = 1;
35
36 // Construct the class.
37 DomainSettingsDialog::DomainSettingsDialog(QWidget *parentWidgetPointer, const int &startType, const QString &domainName) : QDialog(parentWidgetPointer)
38 {
39     // Set the window title.
40     setWindowTitle(i18nc("The domain settings dialog window title", "Domain Settings"));
41
42     // Set the window modality.
43     setWindowModality(Qt::WindowModality::ApplicationModal);
44
45     // Instantiate the user agent helper.
46     userAgentHelperPointer = new UserAgentHelper();
47
48     // Instantiate the domain settings dialog UI.
49     Ui::DomainSettingsDialog domainSettingsDialogUi;
50
51     // Setup the UI.
52     domainSettingsDialogUi.setupUi(this);
53
54     // Get handles for the widgets.
55     domainsListViewPointer = domainSettingsDialogUi.domainsListView;
56     domainSettingsWidgetPointer = domainSettingsDialogUi.domainSettingsWidget;
57     domainNameLineEditPointer = domainSettingsDialogUi.domainNameLineEdit;
58     javaScriptWidgetPointer = domainSettingsDialogUi.javaScriptWidget;
59     javaScriptComboBoxPointer = domainSettingsDialogUi.javaScriptComboBox;
60     javaScriptLabelPointer = domainSettingsDialogUi.javaScriptLabel;
61     localStorageWidgetPointer = domainSettingsDialogUi.localStorageWidget;
62     localStorageComboBoxPointer = domainSettingsDialogUi.localStorageComboBox;
63     localStorageLabelPointer = domainSettingsDialogUi.localStorageLabel;
64     domStorageWidgetPointer = domainSettingsDialogUi.domStorageWidget;
65     domStorageComboBoxPointer = domainSettingsDialogUi.domStorageComboBox;
66     domStorageLabelPointer = domainSettingsDialogUi.domStorageLabel;
67     userAgentWidgetPointer = domainSettingsDialogUi.userAgentWidget;
68     userAgentComboBoxPointer = domainSettingsDialogUi.userAgentComboBox;
69     userAgentLabelPointer = domainSettingsDialogUi.userAgentLabel;
70     zoomFactorWidgetPointer = domainSettingsDialogUi.zoomFactorWidget;
71     zoomFactorComboBoxPointer = domainSettingsDialogUi.zoomFactorComboBox;
72     customZoomFactorSpinBoxPointer = domainSettingsDialogUi.customZoomFactorSpinBox;
73     QPushButton *addDomainButtonPointer = domainSettingsDialogUi.addDomainButton;
74     deleteDomainButtonPointer = domainSettingsDialogUi.deleteDomainButton;
75     QDialogButtonBox *dialogButtonBoxPointer = domainSettingsDialogUi.dialogButtonBox;
76     applyButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::StandardButton::Apply);
77     resetButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::StandardButton::Reset);
78
79     // Create a table model.
80     domainsTableModelPointer = new QSqlTableModel(nullptr, QSqlDatabase::database(DomainsDatabase::CONNECTION_NAME));
81
82     // Set the table for the model.
83     domainsTableModelPointer->setTable(DomainsDatabase::DOMAINS_TABLE);
84
85     // Set the edit strategy to be manual.
86     domainsTableModelPointer->setEditStrategy(QSqlTableModel::EditStrategy::OnManualSubmit);
87
88     // Sort the output alphabetically.
89     domainsTableModelPointer->setSort(1, Qt::SortOrder::AscendingOrder);
90
91     // Set the model for the list view.
92     domainsListViewPointer->setModel(domainsTableModelPointer);
93
94     // Set the visible column to be the domain name.
95     domainsListViewPointer->setModelColumn(1);
96
97     // Get the domains selection model pointer.
98     domainsSelectionModelPointer = domainsListViewPointer->selectionModel();
99
100     // Disable editing of the list view.
101     domainsListViewPointer->setEditTriggers(QAbstractItemView::NoEditTriggers);
102
103     // Read the data from the database and apply it to the table model.
104     domainsTableModelPointer->select();
105
106     // Get the default palette.
107     defaultPalette = javaScriptWidgetPointer->palette();
108
109     // Populate the highlighted palette.
110     highlightedPalette = defaultPalette;
111
112     // Get the default highlight color.
113     QColor highlightColor = defaultPalette.color(QPalette::Highlight);
114
115     // Set the highlight color to be partially transparent.
116     highlightColor.setAlpha(64);
117
118     // Set highlighted background color.
119     highlightedPalette.setColor(QPalette::Window, highlightColor);
120
121     // Setup the dialog according to the start type.
122     switch (startType)
123     {
124         case SHOW_ALL_DOMAINS:
125         {
126             // Select the first entry in the list view.
127             domainsListViewPointer->setCurrentIndex(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)));
128
129             break;
130         }
131
132         case EDIT_DOMAIN:
133         {
134             // Find the index for the new domain.  `1` returns the first match.
135             QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)),
136                                                                              Qt::DisplayRole, domainName, 1, Qt::MatchWrap);
137
138             // Move to the new domain.
139             domainsListViewPointer->setCurrentIndex(newDomainIndex[0]);
140
141             break;
142         }
143     }
144
145     // Populate the domain settings.
146     domainSelected(domainsSelectionModelPointer->currentIndex());
147
148     // Handle clicks on the domains.
149     connect(domainsListViewPointer, SIGNAL(activated(QModelIndex)), this, SLOT(domainSelected(QModelIndex)));
150
151     // Process changes to the domain settings.
152     connect(domainNameLineEditPointer, SIGNAL(textEdited(QString)), this, SLOT(domainNameChanged(QString)));
153     connect(javaScriptComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(javaScriptChanged(int)));
154     connect(localStorageComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(localStorageChanged(int)));
155     connect(domStorageComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(domStorageChanged(int)));
156     connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(QString)), this, SLOT(userAgentChanged(QString)));
157     connect(zoomFactorComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(zoomFactorComboBoxChanged(int)));
158     connect(customZoomFactorSpinBoxPointer, SIGNAL(valueChanged(double)), this, SLOT(customZoomFactorChanged(double)));
159
160     // Connect the buttons.
161     connect(addDomainButtonPointer, SIGNAL(clicked()), this, SLOT(showAddMessageBox()));
162     connect(deleteDomainButtonPointer, SIGNAL(clicked()), this, SLOT(showDeleteMessageBox()));
163     connect(resetButtonPointer, SIGNAL(clicked()), this, SLOT(reset()));
164     connect(dialogButtonBoxPointer, SIGNAL(accepted()), this, SLOT(ok()));
165     connect(applyButtonPointer, SIGNAL(clicked()), this, SLOT(apply()));
166     connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(cancel()));
167
168     // Update the DOM storage status.
169     updateDomStorageStatus();
170
171     // Update the UI.
172     updateUi();
173 }
174
175 void DomainSettingsDialog::apply() const
176 {
177     // Get the current index.
178     QModelIndex currentIndex = domainsListViewPointer->currentIndex();
179
180     // Get the ID of the current index row.
181     QVariant currentId = currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ID)).data();
182
183     // Submit all pending changes.
184     domainsTableModelPointer->submitAll();
185
186     // Find the new index for the selected id.  The `1` keeps searching after the first match.
187     QModelIndexList newIndexList = domainsTableModelPointer->match(currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ID)), Qt::DisplayRole, currentId,
188                                                                    1, Qt::MatchWrap);
189
190     // Select the new index.
191     domainsListViewPointer->setCurrentIndex(newIndexList[0].siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)));
192
193     // Update the UI.
194     updateUi();
195
196     // Emit the domain settings updated signal.
197     emit domainSettingsUpdated();
198 }
199
200 void DomainSettingsDialog::cancel()
201 {
202     // Revert all pending changes.
203     domainsTableModelPointer->revertAll();
204
205     // Close the dialog.
206     reject();
207 }
208
209 void DomainSettingsDialog::customZoomFactorChanged(const double &newValue) const
210 {
211     // Update the domains table model.
212     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)), newValue);
213
214     // Update the UI.
215     updateUi();
216 }
217
218 void DomainSettingsDialog::domStorageChanged(const int &newIndex) const
219 {
220     // Update the domains table model.
221     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)), newIndex);
222
223     // Populate the DOM storage label.
224     populateDomStorageLabel();
225
226     // Update the UI.
227     updateUi();
228 }
229
230 void DomainSettingsDialog::domainNameChanged(const QString &updatedDomainName) const
231 {
232     // Update the domains table model.
233     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex(), updatedDomainName);
234
235     // Update the UI.
236     updateUi();
237 }
238
239 void DomainSettingsDialog::domainSelected(const QModelIndex &modelIndex) const
240 {
241     // Populate the domain name line edit pointer.
242     domainNameLineEditPointer->setText(modelIndex.data().toString());
243
244     // Populate the JavaScript combo box.
245     javaScriptComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)).data().toInt());
246
247     // Populate the local storage combo box.
248     localStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)).data().toInt());
249
250     // Populate the DOM storage combo box.
251     domStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)).data().toInt());
252
253     // Get the user agent string.
254     QString userAgent = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)).data().toString();
255
256     // Get the user agent index.
257     int userAgentIndex = UserAgentHelper::getDomainSettingsUserAgentIndex(userAgent);
258
259     // Set the user agent combo box index.
260     userAgentComboBoxPointer->setCurrentIndex(userAgentIndex);
261
262     // Set the custom user agent if specified.
263     if (userAgentIndex == -1) userAgentComboBoxPointer->setCurrentText(userAgent);
264
265     // Get the zoom factor combo box index.
266     int zoomFactorComboBoxIndex = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)).data().toInt();
267
268     // Populate the zoom factor combo box.
269     zoomFactorComboBoxPointer->setCurrentIndex(zoomFactorComboBoxIndex);
270
271     // Populate the custom zoom factor spin box according to the zoom factor combo box.
272     if (zoomFactorComboBoxIndex == 0)  // System default zoom factor is selected.
273     {
274         // Display the default zoom factor.
275         customZoomFactorSpinBoxPointer->setValue(Settings::zoomFactor());
276
277         // Use the default palette.
278         zoomFactorWidgetPointer->setPalette(defaultPalette);
279     }
280     else  // Custom zoom factor is selected.
281     {
282         // Display the custom zoom factor from the domain settings.
283         customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble());
284
285         // Use the highlighted palette.
286         zoomFactorWidgetPointer->setPalette(highlightedPalette);
287     }
288
289     // Set the initial status of the custom zoom factor spin box.
290     customZoomFactorSpinBoxPointer->setEnabled(zoomFactorComboBoxIndex);
291
292     // Populate the labels.
293     populateJavaScriptLabel();
294     populateLocalStorageLabel();
295     populateDomStorageLabel();
296     populateUserAgentLabel(userAgentComboBoxPointer->currentText());
297
298     // Update the UI.
299     updateUi();
300 }
301
302 void DomainSettingsDialog::javaScriptChanged(const int &newIndex) const
303 {
304     // Update the domains table model.
305     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)), newIndex);
306
307     // Populate the JavaScript label.
308     populateJavaScriptLabel();
309
310     // Update the DOM storage status.
311     updateDomStorageStatus();
312
313     // Update the UI.
314     updateUi();
315 }
316
317 void DomainSettingsDialog::localStorageChanged(const int &newIndex) const
318 {
319     // Update the domains table model.
320     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)), newIndex);
321
322     // Populate the local storage label.
323     populateLocalStorageLabel();
324
325     // Update the DOM storage status.
326     updateDomStorageStatus();
327
328     // Update the UI.
329     updateUi();
330 }
331
332 void DomainSettingsDialog::ok()
333 {
334     // Submit all pending changes.
335     domainsTableModelPointer->submitAll();
336
337     // Emit the domain settings updated signal.
338     emit domainSettingsUpdated();
339
340     // Close the dialog.
341     accept();
342 }
343
344 void DomainSettingsDialog::populateDomStorageLabel() const
345 {
346     // Populate the label according to the currently selected index.
347     switch (domStorageComboBoxPointer->currentIndex())
348     {
349         case (DomainsDatabase::SYSTEM_DEFAULT):
350         {
351             // Set the text according to the system default.
352             if (Settings::domStorageEnabled())
353                 domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.", "DOM storage enabled"));
354             else
355                 domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.", "DOM storage disabled"));
356
357             // Reset the palette.
358             domStorageWidgetPointer->setPalette(defaultPalette);
359
360             break;
361         }
362
363         case (DomainsDatabase::ENABLED):
364         {
365             // Set the enabled text in bold.
366             domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.  The <b> tags should be retained.", "<b>DOM storage enabled</b>"));
367
368             // Set the palette.
369             domStorageWidgetPointer->setPalette(highlightedPalette);
370
371             break;
372         }
373
374         case (DomainsDatabase::DISABLED):
375         {
376             // Set the disabled text in bold.
377             domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.  The <b> tags should be retained.", "<b>DOM storage disabled</b>"));
378
379             // Set the palette.
380             domStorageWidgetPointer->setPalette(highlightedPalette);
381
382             break;
383         }
384     }
385 }
386
387 void DomainSettingsDialog::populateJavaScriptLabel() const
388 {
389     // Populate the label according to the currently selected index.
390     switch (javaScriptComboBoxPointer->currentIndex())
391     {
392         case (DomainsDatabase::SYSTEM_DEFAULT):
393         {
394             // Set the text according to the system default.
395             if (Settings::javaScriptEnabled())
396                 javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript enabled"));
397             else
398                 javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript disabled"));
399
400             // Reset the palette.
401             javaScriptWidgetPointer->setPalette(defaultPalette);
402
403             break;
404         }
405
406         case (DomainsDatabase::ENABLED):
407         {
408             // Set the enabled text in bold.
409             javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.  The <b> tags should be retained.", "<b>JavaScript enabled</b>"));
410
411             // Set the palette.
412             javaScriptWidgetPointer->setPalette(highlightedPalette);
413
414             break;
415         }
416
417         case (DomainsDatabase::DISABLED):
418         {
419             // Set the disabled text in bold.
420             javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.  The <b> tags should be retained.", "<b>JavaScript disabled</b>"));
421
422             // Set the palette.
423             javaScriptWidgetPointer->setPalette(highlightedPalette);
424
425             break;
426         }
427     }
428 }
429
430 void DomainSettingsDialog::populateLocalStorageLabel() const
431 {
432     // Populate the label according to the currently selected index.
433     switch (localStorageComboBoxPointer->currentIndex())
434     {
435         case (DomainsDatabase::SYSTEM_DEFAULT):
436         {
437             // Set the text according to the system default.
438             if (Settings::localStorageEnabled())
439                 localStorageLabelPointer->setText(i18nc("Domain settings local storage label.", "Local storage enabled"));
440             else
441                 localStorageLabelPointer->setText(i18nc("Domain settings local storage label.", "Local storage disabled"));
442
443             // Reset the palette.
444             localStorageWidgetPointer->setPalette(defaultPalette);
445
446             break;
447         }
448
449         case (DomainsDatabase::ENABLED):
450         {
451             // Set the enabled text in bold.
452             localStorageLabelPointer->setText(i18nc("Domain settings local storage label.  The <b> tabs should be retained.", "<b>Local storage enabled</b>"));
453
454             // Set the palette.
455             localStorageWidgetPointer->setPalette(highlightedPalette);
456
457             break;
458         }
459
460         case (DomainsDatabase::DISABLED):
461         {
462             // Set the disabled text in bold.
463             localStorageLabelPointer->setText(i18nc("Domain settings local storage label.  The <b> tags should be retained.", "<b>Local storage disabled</b>"));
464
465             // Set the palette.
466             localStorageWidgetPointer->setPalette(highlightedPalette);
467
468             break;
469         }
470     }
471 }
472
473
474 void DomainSettingsDialog::populateUserAgentLabel(const QString &userAgentName) const
475 {
476     // Populate the label according to the type.
477     if (userAgentName == userAgentHelperPointer->SYSTEM_DEFAULT_TRANSLATED)
478     {
479         // Display the system default user agent name.
480         userAgentLabelPointer->setText(userAgentHelperPointer->getTranslatedUserAgentNameFromDatabaseName(Settings::userAgent()));
481
482         // Reset the palette.
483         userAgentWidgetPointer->setPalette(defaultPalette);
484     }
485     else
486     {
487         // Display the user agent name in bold.
488         userAgentLabelPointer->setText("<strong>" + userAgentName + "</strong>");
489
490         // Set the palette.
491         userAgentWidgetPointer->setPalette(highlightedPalette);
492     }
493 }
494
495 void DomainSettingsDialog::reset() const
496 {
497     // Cancel all pending changes.
498     domainsTableModelPointer->revertAll();
499
500     // Repopulate the domain settings.
501     domainSelected(domainsListViewPointer->currentIndex());
502
503     // Update the UI.
504     updateUi();
505 }
506
507 void DomainSettingsDialog::showAddMessageBox()
508 {
509     // Create an OK flag.
510     bool okClicked;
511
512     // Display a dialog to request the new domain name from the user.
513     QString newDomainName = QInputDialog::getText(this, i18nc("Add domain dialog title", "Add Domain"),
514                                                   i18nc("Add domain message.  The \n\n are newline codes that should be retained",
515                                                         "Add a new domain.  Doing so will also save any pending changes that have been made to other domains.\n\n"
516                                                         "*. may be prepended to a domain to include all subdomains (eg. *.stoutner.com)."),
517                                                   QLineEdit::Normal, QString(), &okClicked);
518
519     // Add the new domain if the user clicked OK.
520     if (okClicked)
521     {
522         // Add the new domain.
523         DomainsDatabase::addDomain(newDomainName);
524
525         // Submit all pending changes.  This reloads the model from the database, getting the new domain added above.
526         domainsTableModelPointer->submitAll();
527
528
529         // Find the index for the new domain.  `-1` allows for multiple entries to be returned.
530         QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)),
531                                                                          Qt::DisplayRole, newDomainName, -1, Qt::MatchWrap);
532
533         // Move to the new domain.  If there are multiple domains with the same name, the new one should be the last in the list.
534         domainsListViewPointer->setCurrentIndex(newDomainIndex[newDomainIndex.size() - 1]);
535
536         // Populate the domain settings.
537         domainSelected(domainsSelectionModelPointer->currentIndex());
538
539         // Update the UI.
540         updateUi();
541
542         // Emit the domain settings updated signal.
543         emit domainSettingsUpdated();
544     }
545 }
546
547 void DomainSettingsDialog::showDeleteMessageBox() const
548 {
549     // Instantiate a delete dialog message box.
550     QMessageBox deleteDialogMessageBox;
551
552     // Set the icon.
553     deleteDialogMessageBox.setIcon(QMessageBox::Warning);
554
555     // Set the window title.
556     deleteDialogMessageBox.setWindowTitle(i18nc("Delete domain dialog title", "Delete Domain"));
557
558     // Set the text.
559     deleteDialogMessageBox.setText(i18nc("Delete domain dialog main message", "Delete the current domain?"));
560
561     // Set the informative text.
562     deleteDialogMessageBox.setInformativeText(i18nc("Delete domain dialog secondary message", "Doing so will also save any pending changes that have been made to other domains."));
563
564     // Set the standard buttons.
565     deleteDialogMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
566
567     // Set the default button.
568     deleteDialogMessageBox.setDefaultButton(QMessageBox::No);
569
570     // Display the dialog and capture the return value.
571     int returnValue = deleteDialogMessageBox.exec();
572
573     // Delete the domain if instructed.
574     if (returnValue == QMessageBox::Yes)
575     {
576         // Get the current index.
577         QModelIndex currentIndex = domainsListViewPointer->currentIndex();
578
579         // Delete the current row.
580         domainsTableModelPointer->removeRow(domainsSelectionModelPointer->currentIndex().row());
581
582         // Submit all pending changes.
583         domainsTableModelPointer->submitAll();
584
585         // Select the row next to the deleted item if one exists.
586         if (domainsTableModelPointer->rowCount() > 0)
587         {
588             // Check the row of the deleted item.
589             if (currentIndex.row() == 0)  // The first row was deleted.
590             {
591                 // Reselect the current index.
592                 domainsListViewPointer->setCurrentIndex(currentIndex);
593             }
594             else  // A subsequent row was deleted.
595             {
596                 // Select the crow above the deleted itemm.
597                 domainsListViewPointer->setCurrentIndex(currentIndex.siblingAtRow(currentIndex.row() - 1));
598             }
599
600             // Populate the domain settings.
601             domainSelected(domainsListViewPointer->currentIndex());
602         }
603
604         // Update the Ui.
605         updateUi();
606
607         // Emit the domain settings updated signal.
608         emit domainSettingsUpdated();
609     }
610 }
611
612 void DomainSettingsDialog::updateDomStorageStatus() const
613 {
614     // Instantiate tracking variables.
615     bool javaScriptEnabled;
616     bool localStorageEnabled;
617
618     // Populate the JavaScript tracker.
619     switch (javaScriptComboBoxPointer->currentIndex())
620     {
621         case (DomainsDatabase::SYSTEM_DEFAULT):
622         {
623             // Update the tracker according to the system default.
624             if (Settings::javaScriptEnabled())
625                 javaScriptEnabled = true;
626             else
627                 javaScriptEnabled = false;
628
629             break;
630         }
631
632         case (DomainsDatabase::ENABLED):
633         {
634             // Update the tracker.
635             javaScriptEnabled = true;
636
637             break;
638         }
639
640         case (DomainsDatabase::DISABLED):
641         {
642             // Update the tracker.
643             javaScriptEnabled = false;
644
645             break;
646         }
647     }
648
649     // Populate the local storage tracker.
650     switch (localStorageComboBoxPointer->currentIndex())
651     {
652         case (DomainsDatabase::SYSTEM_DEFAULT):
653         {
654             // Update the tracker according to the system default.
655             if (Settings::localStorageEnabled())
656                 localStorageEnabled = true;
657             else
658                 localStorageEnabled = false;
659
660             break;
661         }
662
663         case (DomainsDatabase::ENABLED):
664         {
665             // Update the tracker.
666             localStorageEnabled = true;
667
668             break;
669         }
670
671         case (DomainsDatabase::DISABLED):
672         {
673             // Update the tracker.
674             localStorageEnabled = false;
675
676             break;
677         }
678     }
679
680     // Only enable DOM storage if both JavaScript and local storage are enabled.
681     domStorageComboBoxPointer->setEnabled(javaScriptEnabled && localStorageEnabled);
682 }
683
684 void DomainSettingsDialog::updateUi() const
685 {
686     // Update the delete button status.
687     deleteDomainButtonPointer->setEnabled(domainsSelectionModelPointer->hasSelection());
688
689     // Update the reset button status.
690     resetButtonPointer->setEnabled(domainsTableModelPointer->isDirty());
691
692     // Update the apply button status.
693     applyButtonPointer->setEnabled(domainsTableModelPointer->isDirty());
694
695     // Display the domain settings if there is at least one domain.
696     domainSettingsWidgetPointer->setVisible(domainsTableModelPointer->rowCount() > 0);
697 }
698
699 void DomainSettingsDialog::userAgentChanged(const QString &updatedUserAgent) const
700 {
701     // Update the domains table model.
702     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)),
703                                       userAgentHelperPointer->getDatabaseUserAgentNameFromTranslatedName(updatedUserAgent));
704
705     // Populate the user agent label.
706     populateUserAgentLabel(updatedUserAgent);
707
708     // Update the UI.
709     updateUi();
710 }
711
712 void DomainSettingsDialog::zoomFactorComboBoxChanged(const int &newIndex) const
713 {
714     // Get the current model index.
715     QModelIndex modelIndex = domainsSelectionModelPointer->currentIndex();
716
717     // Update the domains table model.
718     domainsTableModelPointer->setData(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)), newIndex);
719
720     // Populate the custom zoom factor spin box according to the zoom factor combo box.
721     if (newIndex == 0)  // System default zoom factor is selected.
722     {
723         // Display the default zoom factor.
724         customZoomFactorSpinBoxPointer->setValue(Settings::zoomFactor());
725
726         // Reset the palette.
727         zoomFactorWidgetPointer->setPalette(defaultPalette);
728     }
729     else  // Custom zoom factor is selected.
730     {
731         // Display the custom zoom factor from the domain settings.
732         customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble());
733
734         // Use the highlighted palette.
735         zoomFactorWidgetPointer->setPalette(highlightedPalette);
736     }
737
738     // Update the status of the custom zoom factor spin box.
739     customZoomFactorSpinBoxPointer->setEnabled(newIndex);
740
741     // Update the UI.
742     updateUi();
743 }