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