2 * Copyright 2022-2024 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
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.
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.
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/>.
20 // Application headers.
21 #include "DomainSettingsDialog.h"
23 #include "ui_DomainSettingsDialog.h"
24 #include "databases/DomainsDatabase.h"
26 // Qt toolkit headers.
27 #include <QInputDialog>
28 #include <QMessageBox>
29 #include <QPushButton>
32 // Define the public static int constants.
33 const int DomainSettingsDialog::SHOW_ALL_DOMAINS = 0;
34 const int DomainSettingsDialog::EDIT_DOMAIN = 1;
36 // Construct the class.
37 DomainSettingsDialog::DomainSettingsDialog(const int &startType, const QString &domainName) : QDialog(nullptr)
39 // Set the window title.
40 setWindowTitle(i18nc("The domain settings dialog window title", "Domain Settings"));
42 // Set the window modality.
43 setWindowModality(Qt::WindowModality::ApplicationModal);
45 // Instantiate the user agent helper.
46 userAgentHelperPointer = new UserAgentHelper();
48 // Instantiate the domain settings dialog UI.
49 Ui::DomainSettingsDialog domainSettingsDialogUi;
52 domainSettingsDialogUi.setupUi(this);
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);
79 // Create a table model.
80 domainsTableModelPointer = new QSqlTableModel(nullptr, QSqlDatabase::database(DomainsDatabase::CONNECTION_NAME));
82 // Set the table for the model.
83 domainsTableModelPointer->setTable(DomainsDatabase::DOMAINS_TABLE);
85 // Set the edit strategy to be manual.
86 domainsTableModelPointer->setEditStrategy(QSqlTableModel::EditStrategy::OnManualSubmit);
88 // Sort the output alphabetically.
89 domainsTableModelPointer->setSort(1, Qt::SortOrder::AscendingOrder);
91 // Set the model for the list view.
92 domainsListViewPointer->setModel(domainsTableModelPointer);
94 // Set the visible column to be the domain name.
95 domainsListViewPointer->setModelColumn(1);
97 // Get the domains selection model pointer.
98 domainsSelectionModelPointer = domainsListViewPointer->selectionModel();
100 // Disable editing of the list view.
101 domainsListViewPointer->setEditTriggers(QAbstractItemView::NoEditTriggers);
103 // Read the data from the database and apply it to the table model.
104 domainsTableModelPointer->select();
106 // Get the default palette.
107 defaultPalette = javaScriptWidgetPointer->palette();
109 // Populate the highlighted palette.
110 highlightedPalette = defaultPalette;
112 // Get the default highlight color.
113 QColor highlightColor = defaultPalette.color(QPalette::Highlight);
115 // Set the highlight color to be partially transparent.
116 highlightColor.setAlpha(64);
118 // Set highlighted background color.
119 highlightedPalette.setColor(QPalette::Window, highlightColor);
121 // Setup the dialog according to the start type.
124 case SHOW_ALL_DOMAINS:
126 // Select the first entry in the list view.
127 domainsListViewPointer->setCurrentIndex(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)));
129 // Populate the domain settings.
130 domainSelected(domainsSelectionModelPointer->currentIndex());
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);
141 // Move to the new domain.
142 domainsListViewPointer->setCurrentIndex(newDomainIndex[0]);
144 // Populate the domain settings.
145 domainSelected(domainsSelectionModelPointer->currentIndex());
151 // Handle clicks on the domains.
152 connect(domainsListViewPointer, SIGNAL(activated(QModelIndex)), this, SLOT(domainSelected(QModelIndex)));
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)));
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()));
175 void DomainSettingsDialog::apply() const
177 // Get the current index.
178 QModelIndex currentIndex = domainsListViewPointer->currentIndex();
180 // Get the ID of the current index row.
181 QVariant currentId = currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ID)).data();
183 // Submit all pending changes.
184 domainsTableModelPointer->submitAll();
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,
190 // Select the new index.
191 domainsListViewPointer->setCurrentIndex(newIndexList[0].siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)));
196 // Emit the domain settings updated signal.
197 emit domainSettingsUpdated();
200 void DomainSettingsDialog::cancel()
202 // Revert all pending changes.
203 domainsTableModelPointer->revertAll();
209 void DomainSettingsDialog::customZoomFactorChanged(const double &newValue) const
211 // Update the domains table model.
212 domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)), newValue);
218 void DomainSettingsDialog::domStorageChanged(const int &newIndex) const
220 // Update the domains table model.
221 domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)), newIndex);
223 // Populate the DOM storage label.
224 populateDomStorageLabel();
230 void DomainSettingsDialog::domainNameChanged(const QString &updatedDomainName) const
232 // Update the domains table model.
233 domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex(), updatedDomainName);
239 void DomainSettingsDialog::domainSelected(const QModelIndex &modelIndex) const
241 // Populate the domain name line edit pointer.
242 domainNameLineEditPointer->setText(modelIndex.data().toString());
244 // Populate the JavaScript combo box.
245 javaScriptComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)).data().toInt());
247 // Populate the local storage combo box.
248 localStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)).data().toInt());
250 // Populate the DOM storage combo box.
251 domStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)).data().toInt());
253 // Get the user agent string.
254 QString userAgent = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)).data().toString();
256 // Get the user agent index.
257 int userAgentIndex = UserAgentHelper::getDomainSettingsUserAgentIndex(userAgent);
259 // Set the user agent combo box index.
260 userAgentComboBoxPointer->setCurrentIndex(userAgentIndex);
262 // Set the custom user agent if specified.
263 if (userAgentIndex == -1) userAgentComboBoxPointer->setCurrentText(userAgent);
265 // Get the zoom factor combo box index.
266 int zoomFactorComboBoxIndex = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)).data().toInt();
268 // Populate the zoom factor combo box.
269 zoomFactorComboBoxPointer->setCurrentIndex(zoomFactorComboBoxIndex);
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.
274 // Display the default zoom factor.
275 customZoomFactorSpinBoxPointer->setValue(Settings::zoomFactor());
277 // Use the default palette.
278 zoomFactorWidgetPointer->setPalette(defaultPalette);
280 else // Custom zoom factor is selected.
282 // Display the custom zoom factor from the domain settings.
283 customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble());
285 // Use the highlighted palette.
286 zoomFactorWidgetPointer->setPalette(highlightedPalette);
289 // Set the initial status of the custom zoom factor spin box.
290 customZoomFactorSpinBoxPointer->setEnabled(zoomFactorComboBoxIndex);
292 // Populate the labels.
293 populateJavaScriptLabel();
294 populateLocalStorageLabel();
295 populateDomStorageLabel();
296 populateUserAgentLabel(userAgentComboBoxPointer->currentText());
302 void DomainSettingsDialog::javaScriptChanged(const int &newIndex) const
304 // Update the domains table model.
305 domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)), newIndex);
307 // Populate the JavaScript label.
308 populateJavaScriptLabel();
314 void DomainSettingsDialog::localStorageChanged(const int &newIndex) const
316 // Update the domains table model.
317 domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)), newIndex);
319 // Populate the local storage label.
320 populateLocalStorageLabel();
326 void DomainSettingsDialog::ok()
328 // Submit all pending changes.
329 domainsTableModelPointer->submitAll();
331 // Emit the domain settings updated signal.
332 emit domainSettingsUpdated();
338 void DomainSettingsDialog::populateDomStorageLabel() const
340 // Populate the label according to the currently selected index.
341 switch (domStorageComboBoxPointer->currentIndex())
343 case (DomainsDatabase::SYSTEM_DEFAULT):
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"));
349 domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.", "DOM storage disabled"));
351 // Reset the palette.
352 domStorageWidgetPointer->setPalette(defaultPalette);
357 case (DomainsDatabase::ENABLED):
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>"));
363 domStorageWidgetPointer->setPalette(highlightedPalette);
368 case (DomainsDatabase::DISABLED):
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>"));
374 domStorageWidgetPointer->setPalette(highlightedPalette);
381 void DomainSettingsDialog::populateJavaScriptLabel() const
383 // Populate the label according to the currently selected index.
384 switch (javaScriptComboBoxPointer->currentIndex())
386 case (DomainsDatabase::SYSTEM_DEFAULT):
388 // Set the text according to the system default.
389 if (Settings::javaScriptEnabled())
390 javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript enabled"));
392 javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript disabled"));
394 // Reset the palette.
395 javaScriptWidgetPointer->setPalette(defaultPalette);
400 case (DomainsDatabase::ENABLED):
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>"));
406 javaScriptWidgetPointer->setPalette(highlightedPalette);
411 case (DomainsDatabase::DISABLED):
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>"));
417 javaScriptWidgetPointer->setPalette(highlightedPalette);
424 void DomainSettingsDialog::populateLocalStorageLabel() const
426 // Populate the label according to the currently selected index.
427 switch (localStorageComboBoxPointer->currentIndex())
429 case (DomainsDatabase::SYSTEM_DEFAULT):
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"));
435 localStorageLabelPointer->setText(i18nc("Domain settings local storage label.", "Local storage disabled"));
437 // Reset the palette.
438 localStorageWidgetPointer->setPalette(defaultPalette);
443 case (DomainsDatabase::ENABLED):
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>"));
449 localStorageWidgetPointer->setPalette(highlightedPalette);
454 case (DomainsDatabase::DISABLED):
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>"));
460 localStorageWidgetPointer->setPalette(highlightedPalette);
468 void DomainSettingsDialog::populateUserAgentLabel(const QString &userAgentName) const
470 // Populate the label according to the type.
471 if (userAgentName == userAgentHelperPointer->SYSTEM_DEFAULT_TRANSLATED)
473 // Display the system default user agent name.
474 userAgentLabelPointer->setText(userAgentHelperPointer->getTranslatedUserAgentNameFromDatabaseName(Settings::userAgent()));
476 // Reset the palette.
477 userAgentWidgetPointer->setPalette(defaultPalette);
481 // Display the user agent name in bold.
482 userAgentLabelPointer->setText("<strong>" + userAgentName + "</strong>");
485 userAgentWidgetPointer->setPalette(highlightedPalette);
489 void DomainSettingsDialog::reset() const
491 // Cancel all pending changes.
492 domainsTableModelPointer->revertAll();
494 // Repopulate the domain settings.
495 domainSelected(domainsListViewPointer->currentIndex());
501 void DomainSettingsDialog::showAddMessageBox()
503 // Create an OK flag.
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);
513 // Add the new domain if the user clicked OK.
516 // Add the new domain.
517 DomainsDatabase::addDomain(newDomainName);
519 // Submit all pending changes. This reloads the model from the database, getting the new domain added above.
520 domainsTableModelPointer->submitAll();
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);
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]);
530 // Populate the domain settings.
531 domainSelected(domainsSelectionModelPointer->currentIndex());
536 // Emit the domain settings updated signal.
537 emit domainSettingsUpdated();
541 void DomainSettingsDialog::showDeleteMessageBox() const
543 // Instantiate a delete dialog message box.
544 QMessageBox deleteDialogMessageBox;
547 deleteDialogMessageBox.setIcon(QMessageBox::Warning);
549 // Set the window title.
550 deleteDialogMessageBox.setWindowTitle(i18nc("Delete domain dialog title", "Delete Domain"));
553 deleteDialogMessageBox.setText(i18nc("Delete domain dialog main message", "Delete the current domain?"));
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."));
558 // Set the standard buttons.
559 deleteDialogMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
561 // Set the default button.
562 deleteDialogMessageBox.setDefaultButton(QMessageBox::No);
564 // Display the dialog and capture the return value.
565 int returnValue = deleteDialogMessageBox.exec();
567 // Delete the domain if instructed.
568 if (returnValue == QMessageBox::Yes)
570 // Get the current index.
571 QModelIndex currentIndex = domainsListViewPointer->currentIndex();
573 // Delete the current row.
574 domainsTableModelPointer->removeRow(domainsSelectionModelPointer->currentIndex().row());
576 // Submit all pending changes.
577 domainsTableModelPointer->submitAll();
579 // Select the row next to the deleted item if one exists.
580 if (domainsTableModelPointer->rowCount() > 0)
582 // Check the row of the deleted item.
583 if (currentIndex.row() == 0) // The first row was deleted.
585 // Reselect the current index.
586 domainsListViewPointer->setCurrentIndex(currentIndex);
588 else // A subsequent row was deleted.
590 // Select the crow above the deleted itemm.
591 domainsListViewPointer->setCurrentIndex(currentIndex.siblingAtRow(currentIndex.row() - 1));
594 // Populate the domain settings.
595 domainSelected(domainsListViewPointer->currentIndex());
601 // Emit the domain settings updated signal.
602 emit domainSettingsUpdated();
606 void DomainSettingsDialog::updateUi() const
608 // Update the delete button status.
609 deleteDomainButtonPointer->setEnabled(domainsSelectionModelPointer->hasSelection());
611 // Update the reset button status.
612 resetButtonPointer->setEnabled(domainsTableModelPointer->isDirty());
614 // Update the apply button status.
615 applyButtonPointer->setEnabled(domainsTableModelPointer->isDirty());
617 // Display the domain settings if there is at least one domain.
618 domainSettingsWidgetPointer->setVisible(domainsTableModelPointer->rowCount() > 0);
621 void DomainSettingsDialog::userAgentChanged(const QString &updatedUserAgent) const
623 // Update the domains table model.
624 domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)),
625 userAgentHelperPointer->getDatabaseUserAgentNameFromTranslatedName(updatedUserAgent));
627 // Populate the user agent label.
628 populateUserAgentLabel(updatedUserAgent);
634 void DomainSettingsDialog::zoomFactorComboBoxChanged(const int &newIndex) const
636 // Get the current model index.
637 QModelIndex modelIndex = domainsSelectionModelPointer->currentIndex();
639 // Update the domains table model.
640 domainsTableModelPointer->setData(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)), newIndex);
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.
645 // Display the default zoom factor.
646 customZoomFactorSpinBoxPointer->setValue(Settings::zoomFactor());
648 // Reset the palette.
649 zoomFactorWidgetPointer->setPalette(defaultPalette);
651 else // Custom zoom factor is selected.
653 // Display the custom zoom factor from the domain settings.
654 customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble());
656 // Use the highlighted palette.
657 zoomFactorWidgetPointer->setPalette(highlightedPalette);
660 // Update the status of the custom zoom factor spin box.
661 customZoomFactorSpinBoxPointer->setEnabled(newIndex);