]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/dialogs/DomainSettingsDialog.cpp
Create new domain settings with the currently applied settings. https://redmine...
[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(const int &startType, const QString &domainName) : QDialog(nullptr)
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             // Populate the domain settings.
130             domainSelected(domainsSelectionModelPointer->currentIndex());
131
132             break;
133         }
134
135         case EDIT_DOMAIN:
136         {
137             // Find the index for the new domain.  `1` returns the first match.
138             QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)),
139                                                                              Qt::DisplayRole, domainName, 1, Qt::MatchWrap);
140
141             // Move to the new domain.
142             domainsListViewPointer->setCurrentIndex(newDomainIndex[0]);
143
144             // Populate the domain settings.
145             domainSelected(domainsSelectionModelPointer->currentIndex());
146
147             break;
148         }
149     }
150
151     // Handle clicks on the domains.
152     connect(domainsListViewPointer, SIGNAL(activated(QModelIndex)), this, SLOT(domainSelected(QModelIndex)));
153
154     // Process changes to the domain settings.
155     connect(domainNameLineEditPointer, SIGNAL(textEdited(QString)), this, SLOT(domainNameChanged(QString)));
156     connect(javaScriptComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(javaScriptChanged(int)));
157     connect(localStorageComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(localStorageChanged(int)));
158     connect(domStorageComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(domStorageChanged(int)));
159     connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(QString)), this, SLOT(userAgentChanged(QString)));
160     connect(zoomFactorComboBoxPointer, SIGNAL(currentIndexChanged(int)), this, SLOT(zoomFactorComboBoxChanged(int)));
161     connect(customZoomFactorSpinBoxPointer, SIGNAL(valueChanged(double)), this, SLOT(customZoomFactorChanged(double)));
162
163     // Connect the buttons.
164     connect(addDomainButtonPointer, SIGNAL(clicked()), this, SLOT(showAddMessageBox()));
165     connect(deleteDomainButtonPointer, SIGNAL(clicked()), this, SLOT(showDeleteMessageBox()));
166     connect(resetButtonPointer, SIGNAL(clicked()), this, SLOT(reset()));
167     connect(dialogButtonBoxPointer, SIGNAL(accepted()), this, SLOT(ok()));
168     connect(applyButtonPointer, SIGNAL(clicked()), this, SLOT(apply()));
169     connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(cancel()));
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 UI.
311     updateUi();
312 }
313
314 void DomainSettingsDialog::localStorageChanged(const int &newIndex) const
315 {
316     // Update the domains table model.
317     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)), newIndex);
318
319     // Populate the local storage label.
320     populateLocalStorageLabel();
321
322     // Update the UI.
323     updateUi();
324 }
325
326 void DomainSettingsDialog::ok()
327 {
328     // Submit all pending changes.
329     domainsTableModelPointer->submitAll();
330
331     // Emit the domain settings updated signal.
332     emit domainSettingsUpdated();
333
334     // Close the dialog.
335     accept();
336 }
337
338 void DomainSettingsDialog::populateDomStorageLabel() const
339 {
340     // Populate the label according to the currently selected index.
341     switch (domStorageComboBoxPointer->currentIndex())
342     {
343         case (DomainsDatabase::SYSTEM_DEFAULT):
344         {
345             // Set the text according to the system default.
346             if (Settings::domStorageEnabled())
347                 domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.", "DOM storage enabled"));
348             else
349                 domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.", "DOM storage disabled"));
350
351             // Reset the palette.
352             domStorageWidgetPointer->setPalette(defaultPalette);
353
354             break;
355         }
356
357         case (DomainsDatabase::ENABLED):
358         {
359             // Set the enabled text in bold.
360             domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.  The <b> tags should be retained.", "<b>DOM storage enabled</b>"));
361
362             // Set the palette.
363             domStorageWidgetPointer->setPalette(highlightedPalette);
364
365             break;
366         }
367
368         case (DomainsDatabase::DISABLED):
369         {
370             // Set the disabled text in bold.
371             domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.  The <b> tags should be retained.", "<b>DOM storage disabled</b>"));
372
373             // Set the palette.
374             domStorageWidgetPointer->setPalette(highlightedPalette);
375
376             break;
377         }
378     }
379 }
380
381 void DomainSettingsDialog::populateJavaScriptLabel() const
382 {
383     // Populate the label according to the currently selected index.
384     switch (javaScriptComboBoxPointer->currentIndex())
385     {
386         case (DomainsDatabase::SYSTEM_DEFAULT):
387         {
388             // Set the text according to the system default.
389             if (Settings::javaScriptEnabled())
390                 javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript enabled"));
391             else
392                 javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript disabled"));
393
394             // Reset the palette.
395             javaScriptWidgetPointer->setPalette(defaultPalette);
396
397             break;
398         }
399
400         case (DomainsDatabase::ENABLED):
401         {
402             // Set the enabled text in bold.
403             javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.  The <b> tags should be retained.", "<b>JavaScript enabled</b>"));
404
405             // Set the palette.
406             javaScriptWidgetPointer->setPalette(highlightedPalette);
407
408             break;
409         }
410
411         case (DomainsDatabase::DISABLED):
412         {
413             // Set the disabled text in bold.
414             javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.  The <b> tags should be retained.", "<b>JavaScript disabled</b>"));
415
416             // Set the palette.
417             javaScriptWidgetPointer->setPalette(highlightedPalette);
418
419             break;
420         }
421     }
422 }
423
424 void DomainSettingsDialog::populateLocalStorageLabel() const
425 {
426     // Populate the label according to the currently selected index.
427     switch (localStorageComboBoxPointer->currentIndex())
428     {
429         case (DomainsDatabase::SYSTEM_DEFAULT):
430         {
431             // Set the text according to the system default.
432             if (Settings::localStorageEnabled())
433                 localStorageLabelPointer->setText(i18nc("Domain settings local storage label.", "Local storage enabled"));
434             else
435                 localStorageLabelPointer->setText(i18nc("Domain settings local storage label.", "Local storage disabled"));
436
437             // Reset the palette.
438             localStorageWidgetPointer->setPalette(defaultPalette);
439
440             break;
441         }
442
443         case (DomainsDatabase::ENABLED):
444         {
445             // Set the enabled text in bold.
446             localStorageLabelPointer->setText(i18nc("Domain settings local storage label.  The <b> tabs should be retained.", "<b>Local storage enabled</b>"));
447
448             // Set the palette.
449             localStorageWidgetPointer->setPalette(highlightedPalette);
450
451             break;
452         }
453
454         case (DomainsDatabase::DISABLED):
455         {
456             // Set the disabled text in bold.
457             localStorageLabelPointer->setText(i18nc("Domain settings local storage label.  The <b> tags should be retained.", "<b>Local storage disabled</b>"));
458
459             // Set the palette.
460             localStorageWidgetPointer->setPalette(highlightedPalette);
461
462             break;
463         }
464     }
465 }
466
467
468 void DomainSettingsDialog::populateUserAgentLabel(const QString &userAgentName) const
469 {
470     // Populate the label according to the type.
471     if (userAgentName == userAgentHelperPointer->SYSTEM_DEFAULT_TRANSLATED)
472     {
473         // Display the system default user agent name.
474         userAgentLabelPointer->setText(userAgentHelperPointer->getTranslatedUserAgentNameFromDatabaseName(Settings::userAgent()));
475
476         // Reset the palette.
477         userAgentWidgetPointer->setPalette(defaultPalette);
478     }
479     else
480     {
481         // Display the user agent name in bold.
482         userAgentLabelPointer->setText("<strong>" + userAgentName + "</strong>");
483
484         // Set the palette.
485         userAgentWidgetPointer->setPalette(highlightedPalette);
486     }
487 }
488
489 void DomainSettingsDialog::reset() const
490 {
491     // Cancel all pending changes.
492     domainsTableModelPointer->revertAll();
493
494     // Repopulate the domain settings.
495     domainSelected(domainsListViewPointer->currentIndex());
496
497     // Update the UI.
498     updateUi();
499 }
500
501 void DomainSettingsDialog::showAddMessageBox()
502 {
503     // Create an OK flag.
504     bool okClicked;
505
506     // Display a dialog to request the new domain name from the user.
507     QString newDomainName = QInputDialog::getText(this, i18nc("Add domain dialog title", "Add Domain"),
508                                                   i18nc("Add domain message.  The \n\n are newline codes that should be retained",
509                                                         "Add a new domain.  Doing so will also save any pending changes that have been made to other domains.\n\n"
510                                                         "*. may be prepended to a domain to include all subdomains (eg. *.stoutner.com)."),
511                                                   QLineEdit::Normal, QString(), &okClicked);
512
513     // Add the new domain if the user clicked OK.
514     if (okClicked)
515     {
516         // Add the new domain.
517         DomainsDatabase::addDomain(newDomainName);
518
519         // Submit all pending changes.  This reloads the model from the database, getting the new domain added above.
520         domainsTableModelPointer->submitAll();
521
522
523         // Find the index for the new domain.  `-1` allows for multiple entries to be returned.
524         QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)),
525                                                                          Qt::DisplayRole, newDomainName, -1, Qt::MatchWrap);
526
527         // Move to the new domain.  If there are multiple domains with the same name, the new one should be the last in the list.
528         domainsListViewPointer->setCurrentIndex(newDomainIndex[newDomainIndex.size() - 1]);
529
530         // Populate the domain settings.
531         domainSelected(domainsSelectionModelPointer->currentIndex());
532
533         // Update the UI.
534         updateUi();
535
536         // Emit the domain settings updated signal.
537         emit domainSettingsUpdated();
538     }
539 }
540
541 void DomainSettingsDialog::showDeleteMessageBox() const
542 {
543     // Instantiate a delete dialog message box.
544     QMessageBox deleteDialogMessageBox;
545
546     // Set the icon.
547     deleteDialogMessageBox.setIcon(QMessageBox::Warning);
548
549     // Set the window title.
550     deleteDialogMessageBox.setWindowTitle(i18nc("Delete domain dialog title", "Delete Domain"));
551
552     // Set the text.
553     deleteDialogMessageBox.setText(i18nc("Delete domain dialog main message", "Delete the current domain?"));
554
555     // Set the informative text.
556     deleteDialogMessageBox.setInformativeText(i18nc("Delete domain dialog secondary message", "Doing so will also save any pending changes that have been made to other domains."));
557
558     // Set the standard buttons.
559     deleteDialogMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
560
561     // Set the default button.
562     deleteDialogMessageBox.setDefaultButton(QMessageBox::No);
563
564     // Display the dialog and capture the return value.
565     int returnValue = deleteDialogMessageBox.exec();
566
567     // Delete the domain if instructed.
568     if (returnValue == QMessageBox::Yes)
569     {
570         // Get the current index.
571         QModelIndex currentIndex = domainsListViewPointer->currentIndex();
572
573         // Delete the current row.
574         domainsTableModelPointer->removeRow(domainsSelectionModelPointer->currentIndex().row());
575
576         // Submit all pending changes.
577         domainsTableModelPointer->submitAll();
578
579         // Select the row next to the deleted item if one exists.
580         if (domainsTableModelPointer->rowCount() > 0)
581         {
582             // Check the row of the deleted item.
583             if (currentIndex.row() == 0)  // The first row was deleted.
584             {
585                 // Reselect the current index.
586                 domainsListViewPointer->setCurrentIndex(currentIndex);
587             }
588             else  // A subsequent row was deleted.
589             {
590                 // Select the crow above the deleted itemm.
591                 domainsListViewPointer->setCurrentIndex(currentIndex.siblingAtRow(currentIndex.row() - 1));
592             }
593
594             // Populate the domain settings.
595             domainSelected(domainsListViewPointer->currentIndex());
596         }
597
598         // Update the Ui.
599         updateUi();
600
601         // Emit the domain settings updated signal.
602         emit domainSettingsUpdated();
603     }
604 }
605
606 void DomainSettingsDialog::updateUi() const
607 {
608     // Update the delete button status.
609     deleteDomainButtonPointer->setEnabled(domainsSelectionModelPointer->hasSelection());
610
611     // Update the reset button status.
612     resetButtonPointer->setEnabled(domainsTableModelPointer->isDirty());
613
614     // Update the apply button status.
615     applyButtonPointer->setEnabled(domainsTableModelPointer->isDirty());
616
617     // Display the domain settings if there is at least one domain.
618     domainSettingsWidgetPointer->setVisible(domainsTableModelPointer->rowCount() > 0);
619 }
620
621 void DomainSettingsDialog::userAgentChanged(const QString &updatedUserAgent) const
622 {
623     // Update the domains table model.
624     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)),
625                                       userAgentHelperPointer->getDatabaseUserAgentNameFromTranslatedName(updatedUserAgent));
626
627     // Populate the user agent label.
628     populateUserAgentLabel(updatedUserAgent);
629
630     // Update the UI.
631     updateUi();
632 }
633
634 void DomainSettingsDialog::zoomFactorComboBoxChanged(const int &newIndex) const
635 {
636     // Get the current model index.
637     QModelIndex modelIndex = domainsSelectionModelPointer->currentIndex();
638
639     // Update the domains table model.
640     domainsTableModelPointer->setData(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)), newIndex);
641
642     // Populate the custom zoom factor spin box according to the zoom factor combo box.
643     if (newIndex == 0)  // System default zoom factor is selected.
644     {
645         // Display the default zoom factor.
646         customZoomFactorSpinBoxPointer->setValue(Settings::zoomFactor());
647
648         // Reset the palette.
649         zoomFactorWidgetPointer->setPalette(defaultPalette);
650     }
651     else  // Custom zoom factor is selected.
652     {
653         // Display the custom zoom factor from the domain settings.
654         customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble());
655
656         // Use the highlighted palette.
657         zoomFactorWidgetPointer->setPalette(highlightedPalette);
658     }
659
660     // Update the status of the custom zoom factor spin box.
661     customZoomFactorSpinBoxPointer->setEnabled(newIndex);
662
663     // Update the UI.
664     updateUi();
665 }