]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/commitdiff
Enable spell checking. https://redmine.stoutner.com/issues/840
authorSoren Stoutner <soren@stoutner.com>
Wed, 8 Feb 2023 01:14:07 +0000 (18:14 -0700)
committerSoren Stoutner <soren@stoutner.com>
Wed, 8 Feb 2023 01:14:07 +0000 (18:14 -0700)
src/CMakeLists.txt
src/settings/Settings.kcfg
src/settings/Settings.kcfgc
src/uis/SettingsGeneral.ui
src/uis/SettingsPrivacy.ui
src/uis/SettingsSpellCheck.ui [new file with mode: 0644]
src/widgets/TabWidget.cpp
src/widgets/TabWidget.h
src/windows/BrowserWindow.cpp

index 8278a21d38fb71d90ca7699b197eaf1c07a8b32a..2d1340b2fa06eac0509103d111fc3b8d9489c8b1 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2022 Soren Stoutner <soren@stoutner.com>.
+# Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
 #
 # This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 #
@@ -43,6 +43,7 @@ ki18n_wrap_ui(privacy-browser
     uis/SaveDialog.ui
     uis/SettingsGeneral.ui
     uis/SettingsPrivacy.ui
+    uis/SettingsSpellCheck.ui
     uis/TabWidget.ui
 )
 
index 9b46d73a1ef8455e8fe2491a484981c7f97a551b..9f8a87d30765960e3e1a1876b82be3f6859a56f8 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   You should have received a copy of the GNU General Public License
   along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>. -->
 
-<!-- The options are partially documented at <https://api.kde.org/frameworks/kconfig/html/classKConfigSkeleton.html>. -->
+<!-- The options are partially documented at the following URLs:
+    <https://api.kde.org/frameworks/kconfig/html/classKConfigSkeleton.html>
+    <https://api.kde.org/frameworks/kconfig/html/classKCoreConfigSkeleton.html> -->
 <kcfg
     xmlns="http://www.kde.org/standards/kcfg/1.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
 
-    <!-- This is the name of the file located in `~/.config/` where the settings are stored. -->
+    <!-- The name of the file located in `~/.config/` where the settings are stored. -->
     <kcfgfile name="privacybrowser"/>
 
     <group name="Privacy">
             <default>true</default>
         </entry>
     </group>
+
+    <group name="SpellCheck">
+        <entry name="spellCheckLanguages" type="StringList">
+            <default>en_US</default>
+        </entry>
+    </group>
 </kcfg>
index 42940f7c9921c8cb1c0710c024cce03207757657..dce7cb8f7b95450a8245234ff9885cd4b8588876 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+# Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
 #
 # This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 #
@@ -15,6 +15,9 @@
 # You should have received a copy of the GNU General Public License
 # along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
 
+# The options for this file are partially specified at the following URLs:
+# <https://api.kde.org/frameworks/kconfig/html/kconfig_compiler.html>
+# <https://develop.kde.org/docs/use/configuration/kconfig_xt/>
 
 # Specify the KConfig file.
 File=Settings.kcfg
@@ -24,3 +27,6 @@ ClassName=Settings
 
 # Make the generated class a singleton.
 Singleton=true
+
+# List of variables that can be manually changed.
+Mutators=spellCheckLanguages
index 38fcfd47318b3a8fc88b75da02fde079a9fc5809..d2911fa04108ed598f024528902a0f0808024b9c 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
index 2103b6e3f4b9fde1a2ab03171a8f482e28364cf8..098ba09b638b798a556d8b75fd99b37cf738ec38 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
diff --git a/src/uis/SettingsSpellCheck.ui b/src/uis/SettingsSpellCheck.ui
new file mode 100644 (file)
index 0000000..eb16b6a
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+
+  Privacy Browser PC is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser PC is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<ui version="4.0">
+    <!-- The name of the generated class. -->
+    <class>SpellCheckSettings</class>
+
+    <widget class="QWidget">
+        <layout class="QVBoxLayout">
+            <!-- Instructions. -->
+            <item>
+                <widget class="QLabel" name="spellCheckInstructions">
+                    <property name="text">
+                        <string>Spell checking languages can be added by installing the Hunspell language packages.  One or more languages can be selected.  All selected languages will be applied simultaneously.</string>
+                    </property>
+
+                    <property name="wordWrap">
+                        <bool>true</bool>
+                    </property>
+                </widget>
+            </item>
+
+            <!-- Selection list. -->
+            <item>
+                <widget class="QListWidget" name="spellCheckListWidget">
+                    <property name="sizePolicy">
+                        <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
+                            <horstretch>0</horstretch>
+                            <verstretch>0</verstretch>
+                        </sizepolicy>
+                    </property>
+                </widget>
+            </item>
+        </layout>
+    </widget>
+</ui>
index aee71d73820d3db97c3f3e2ac433be8731fddb47..a5ecefc3b96579b75f1e0b5404b7753f2c720322 100644 (file)
@@ -341,7 +341,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     webEngineProfilePointer->setSpellCheckEnabled(true);
 
     // Set the spell check language.
-    webEngineProfilePointer->setSpellCheckLanguages({QLatin1String("en_US")});
+    webEngineProfilePointer->setSpellCheckLanguages(Settings::spellCheckLanguages());
 
     // Populate the zoom factor.  This is necessary if a URL is being loaded, like a local URL, that does not trigger `applyDomainSettings()`.
     privacyWebEngineViewPointer->setZoomFactor(Settings::zoomFactor());
@@ -554,7 +554,7 @@ void TabWidget::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
     // Store the search engine string.
     searchEngineUrl = SearchEngineHelper::getSearchUrl(searchEngineName);
 
-    // Update the search engine actionas.
+    // Update the search engine actions.
     emit updateSearchEngineActions(searchEngineName, false);
 }
 
@@ -586,6 +586,28 @@ void TabWidget::applyOnTheFlyZoomFactor(const double &zoomFactor)
     currentPrivacyWebEngineViewPointer->setZoomFactor(zoomFactor);
 }
 
+void TabWidget::applySpellCheckLanguages() const
+{
+    // Get the number of tab.
+    int numberOfTabs = tabWidgetPointer->count();
+
+    // Set the spell check languages for each tab.
+    for (int i = 0; i < numberOfTabs; ++i)
+    {
+        // Get the WebEngine view pointer.
+        PrivacyWebEngineView *webEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(tabWidgetPointer->currentWidget());
+
+        // Get the WebEngine page pointer.
+        QWebEnginePage *webEnginePagePointer = webEngineViewPointer->page();
+
+        // Get the WebEngine profile pointer.
+        QWebEngineProfile *webEngineProfilePointer = webEnginePagePointer->profile();
+
+        // Set the spell check languages.
+        webEngineProfilePointer->setSpellCheckLanguages(Settings::spellCheckLanguages());
+    }
+}
+
 void TabWidget::back() const
 {
     // Go back.
@@ -1058,7 +1080,7 @@ void TabWidget::toggleJavaScript() const
 
 void TabWidget::toggleLocalStorage()
 {
-    // Toggle local storeage.
+    // Toggle local storage.
     currentPrivacyWebEngineViewPointer->localStorageEnabled = !currentPrivacyWebEngineViewPointer->localStorageEnabled;
 
     // Update the local storage action.
index 4b247f71d83fa37b3c7d2c1dec670e9457a4e45a..72a50a027347e822826d874fecf77f44c19d7f62 100644 (file)
@@ -51,6 +51,7 @@ public:
 
     // The public functions.
     void applyOnTheFlyZoomFactor(const double &zoomFactor);
+    void applySpellCheckLanguages() const;
     PrivacyWebEngineView* loadBlankInitialWebsite();
     void loadInitialWebsite();
     void findPrevious(const QString &text) const;
index 5960393f1da4b4fb535b4383463ce4ff46f08a3c..efa87ab0ea6fe57d710ea04a6984251a93cec00c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
  *
@@ -20,8 +20,9 @@
 // Application headers.
 #include "BrowserWindow.h"
 #include "Settings.h"
-#include "ui_SettingsPrivacy.h"
 #include "ui_SettingsGeneral.h"
+#include "ui_SettingsPrivacy.h"
+#include "ui_SettingsSpellCheck.h"
 #include "dialogs/CookiesDialog.h"
 #include "dialogs/DomainSettingsDialog.h"
 #include "helpers/SearchEngineHelper.h"
@@ -631,14 +632,17 @@ void BrowserWindow::showSettingsDialog()
     // Create the settings widgets.
     QWidget *privacySettingsWidgetPointer = new QWidget;
     QWidget *generalSettingsWidgetPointer = new QWidget;
+    QWidget *spellCheckSettingsWidgetPointer = new QWidget;
 
     // Instantiate the settings UI.
     Ui::PrivacySettings privacySettingsUi;
     Ui::GeneralSettings generalSettingsUi;
+    Ui::SpellCheckSettings spellCheckSettingsUi;
 
     // Setup the UI to display the settings widgets.
     privacySettingsUi.setupUi(privacySettingsWidgetPointer);
     generalSettingsUi.setupUi(generalSettingsWidgetPointer);
+    spellCheckSettingsUi.setupUi(spellCheckSettingsWidgetPointer);
 
     // Get handles for the widgets.
     QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
@@ -647,6 +651,7 @@ void BrowserWindow::showSettingsDialog()
     searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
     downloadLocationComboBoxPointer = generalSettingsUi.kcfg_downloadLocation;
     QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
+    QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
 
     // Populate the combo box labels.
     updateUserAgentLabel(userAgentComboBoxPointer->currentText());
@@ -659,12 +664,51 @@ void BrowserWindow::showSettingsDialog()
     // Connect the download location directory browse button.
     connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadLocationBrowseDialog()));
 
+    // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
+    QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
+
+    // Get a dictionaries string list.
+    QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
+
+    // Remove the `.bdic` file extensions from the dictionaries list.
+    dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
+
+    // Get a list of the enabled spell check languages.
+    QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
+
+    // Add each dictionary to the spell check list widget.
+    foreach(QString dictionaryString, dictionariesStringList)
+    {
+        // Create a new list widget item pointer named after the dictionary string.
+        QListWidgetItem *listWidgetItemPointer = new QListWidgetItem(dictionaryString, spellCheckListWidgetPointer);
+
+        // Set the list widget item pointer to be checkable.
+        listWidgetItemPointer->setFlags(listWidgetItemPointer->flags() | Qt::ItemIsUserCheckable);
+
+        // Check the language if it is currently enabled.
+        if (enabledSpellCheckLanguagesList.contains(dictionaryString))
+            listWidgetItemPointer->setCheckState(Qt::Checked);
+        else
+            listWidgetItemPointer->setCheckState(Qt::Unchecked);
+
+        // Add the list widget item to the widget.
+        spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
+    }
+
+    // Get a handle for the KConfig skeleton.
+    KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
+
     // Instantiate a settings config dialog from the settings.kcfg file.
-    configDialogPointer = new KConfigDialog(this, QStringLiteral("settings"), Settings::self());
+    configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
 
     // Add the settings widgets as config dialog pages.
-    configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("@title:tab", "Privacy"), QStringLiteral("privacy-browser"));
-    configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("@title:tab", "General"), QStringLiteral("breeze-settings"));
+    configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacy-browser"));
+    configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), QLatin1String("breeze-settings"));
+    configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
+
+    // Get handles for the buttons.
+    QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
+    QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
 
     // Prevent interaction with the parent window while the dialog is open.
     configDialogPointer->setWindowModality(Qt::WindowModal);
@@ -681,7 +725,44 @@ void BrowserWindow::showSettingsDialog()
     // Expand the config dialog.
     configDialogPointer->resize(1000, 500);
 
-    // Apply the settings when they are updated.
+    // Create a save spell check languages lambda.
+    auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
+    {
+        // Create a list of enabled languages.
+        QStringList newSpellCheckLanguages = QStringList();
+
+        // Get a count of all the languages.
+        int allLanguagesCount = spellCheckListWidgetPointer->count();
+
+        // Get a list of all the checked languages.
+        for (int i = 0; i < allLanguagesCount; ++i) {
+            // Get the language item.
+            QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
+
+            // Add the item to the enabled languages if it is checked.
+            if (languageItemPointer->checkState() == Qt::Checked)
+                newSpellCheckLanguages.append(languageItemPointer->text());
+        }
+
+        // Update the spell check languages.
+        if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
+        {
+            // Update the spell check languages.
+            Settings::setSpellCheckLanguages(newSpellCheckLanguages);
+
+            // Write the settings to disk.
+            kConfigSkeletonPointer->save();
+        }
+
+        // Apply the spell check languages.
+        tabWidgetPointer->applySpellCheckLanguages();
+    };
+
+    // Process
+    connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
+    connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
+
+    // Apply the settings handled by KConfig.
     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
 }