From b44963d572b5ed2995936d1a334b3632dfbbd6d7 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Mon, 4 Oct 2021 17:39:24 +0200 Subject: [PATCH] Copy SonnetConfigPage since we can't put it in Sonnet for now --- imports/NeoChat/Settings/SonnetConfigPage.qml | 336 ++++++++++++++++++ imports/NeoChat/Settings/qmldir | 1 + res.qrc | 1 + 3 files changed, 338 insertions(+) create mode 100644 imports/NeoChat/Settings/SonnetConfigPage.qml diff --git a/imports/NeoChat/Settings/SonnetConfigPage.qml b/imports/NeoChat/Settings/SonnetConfigPage.qml new file mode 100644 index 000000000..255f82421 --- /dev/null +++ b/imports/NeoChat/Settings/SonnetConfigPage.qml @@ -0,0 +1,336 @@ +// SPDX-FileCopyrightText: 2021 Carl Schwan +// SPDX-License-Identifier: LGPL-2.1-or-later + +import QtQml 2.15 +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQuick.Layouts 1.15 +import org.kde.kirigami 2.15 as Kirigami +import org.kde.sonnet 1.0 as Sonnet + +Kirigami.Page { + id: page + + /** + * This property holds whether the setting on that page are automatically + * applied or whether the user can apply then manually. By default, false. + */ + property bool instantApply: false + + /** + * This property holds whether the ListViews inside the page should get + * extra padding and a background. By default, use the Kirigami.ApplicationWindow + * wideMode value. + */ + property bool wideMode: QQC2.ApplicationWindow.window.wideMode ?? QQC2.ApplicationWindow.window.width > Kirigami.Units.gridUnit * 40 + + /** + * Signal emmited when the user decide to discard it's change and close the + * setting page. + * + * For example when using the ConfigPage inside Kirigami PageRow: + * + * \code + * Sonnet.ConfigPage { + * onClose: applicationWindow().pageStack.pop(); + * } + * \endcode + */ + signal close() + + function onBackRequested(event) { + if (settings.modified) { + applyDialog.open(); + event.accepted = true; + } + if (dialog) { + dialog.close(); + } + } + title: i18nc('@window:title', 'Spellchecking') + + QQC2.Dialog { + id: applyDialog + title: qsTr("Apply Settings") + contentItem: QQC2.Label { + text: qsTr("The settings of the current module have changed.
Do you want to apply the changes or discard them?") + } + standardButtons: QQC2.Dialog.Ok | QQC2.Dialog.Cancel | QQC2.Dialog.Discard + + onAccepted: { + settings.save(); + applyDialog.close(); + page.close(); + } + onDiscarded: { + applyDialog.close(); + page.close(); + } + onRejected: applyDialog.close(); + } + + onWideModeChanged: scroll.background.visible = wideMode; + + leftPadding: wideMode ? Kirigami.Units.gridUnit : 0 + topPadding: wideMode ? Kirigami.Units.gridUnit : 0 + bottomPadding: wideMode ? Kirigami.Units.gridUnit : 0 + rightPadding: wideMode ? Kirigami.Units.gridUnit : 0 + + property var dialog: null + + Sonnet.Settings { + id: settings + } + + ColumnLayout { + anchors.fill: parent + + Kirigami.FormLayout { + Layout.fillWidth: true + Layout.leftMargin: wideMode ? 0 : Kirigami.Units.largeSpacing + Layout.rightMargin: wideMode ? 0 : Kirigami.Units.largeSpacing + + QQC2.ComboBox { + Kirigami.FormData.label: i18n("Selected default language:") + model: settings.dictionaryModel + textRole: "display" + valueRole: "languageCode" + Component.onCompleted: currentIndex = indexOfValue(settings.defaultLanguage); + onActivated: { + settings.defaultLanguage = currentValue; + } + } + + QQC2.Button { + text: i18n("Open Personal Dictionary") + onClicked: if (!dialog) { + if (Kirigami.Settings.isMobile) { + dialog = mobileSheet.createObject(page, {settings: settings}); + dialog.open(); + } else { + dialog = desktopSheet.createObject(page, {settings: settings}) + dialog.show(); + } + } else { + if (Kirigami.Settings.isMobile) { + dialog.open(); + } else { + dialog.show(); + } + } + } + + QQC2.CheckBox { + Kirigami.FormData.label: i18n("Options:") + checked: settings.checkerEnabledByDefault + text: i18n("Enable automatic spell checking") + onCheckedChanged: { + settings.checkerEnabledByDefault = checked; + if (instantApply) { + settings.save(); + } + } + } + + QQC2.CheckBox { + checked: settings.skipUppercase + text: i18n("Ignore uppercase words") + onCheckedChanged: { + settings.skipUppercase = checked; + if (instantApply) { + settings.save(); + } + } + } + + QQC2.CheckBox { + checked: settings.skipRunTogether + text: i18n("Ignore hyphenated words") + onCheckedChanged: { + settings.skipRunTogether = checked; + if (instantApply) { + settings.save(); + } + } + } + + QQC2.CheckBox { + id: autodetectLanguageCheckbox + checked: settings.autodetectLanguage + text: i18n("Detect language automatically") + onCheckedChanged: { + settings.autodetectLanguage = checked; + if (instantApply) { + settings.save(); + } + } + } + } + + Kirigami.Heading { + level: 2 + text: i18n("Spell checking languages") + wrapMode: Text.WordWrap + Layout.fillWidth: true + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.leftMargin: wideMode ? 0 : Kirigami.Units.largeSpacing + Layout.rightMargin: wideMode ? 0 : Kirigami.Units.largeSpacing + } + QQC2.Label { + text: i18n("%1 will provide spell checking and suggestions for the languages listed here when autodetection is enabled.", Qt.application.displayName) + wrapMode: Text.WordWrap + Layout.fillWidth: true + Layout.leftMargin: wideMode ? 0 : Kirigami.Units.largeSpacing + Layout.rightMargin: wideMode ? 0 : Kirigami.Units.largeSpacing + } + + QQC2.ScrollView { + id: scroll + Layout.fillWidth: true + Layout.fillHeight: true + enabled: autodetectLanguageCheckbox.checked + Component.onCompleted: background.visible = wideMode + ListView { + clip: true + model: settings.dictionaryModel + delegate: Kirigami.CheckableListItem { + label: model.display + action: Kirigami.Action { + onTriggered: model.checked = checked + } + checked: model.checked + trailing: Kirigami.Icon { + source: "favorite" + visible: model.isDefault + HoverHandler { + id: hover + } + QQC2.ToolTip { + visible: hover.hovered + text: qsTr("Default Language") + } + } + } + } + } + } + + component SheetHeader : RowLayout { + QQC2.TextField { + id: dictionaryField + Layout.fillWidth: true + placeholderText: i18n("Add a new word to your personal dictionary…") + } + QQC2.Button { + text: i18nc("@action:button", "Add word") + icon.name: "list-add" + enabled: dictionaryField.text.length > 0 + onClicked: { + add(dictionaryField.text); + dictionaryField.clear(); + if (instantApply) { + settings.save(); + } + } + Layout.rightMargin: Kirigami.Units.largeSpacing + } + } + + Component { + id: desktopSheet + QQC2.ApplicationWindow { + id: window + required property Sonnet.Settings settings + title: i18n("Spell checking dictionary") + width: Kirigami.Units.gridUnit * 20 + height: Kirigami.Units.gridUnit * 20 + flags: Qt.Dialog | Qt.WindowCloseButtonHint + header: Kirigami.AbstractApplicationHeader { + leftPadding: Kirigami.Units.smallSpacing + rightPadding: Kirigami.Units.smallSpacing + contentItem: SheetHeader { + anchors.fill: parent + } + } + QQC2.ScrollView { + anchors.fill: parent + ListView { + model: settings.currentIgnoreList + delegate: Kirigami.BasicListItem { + label: model.modelData + trailing: QQC2.ToolButton { + icon.name: "delete" + onClicked: { + remove(modelData) + if (instantApply) { + settings.save(); + } + } + QQC2.ToolTip { + text: i18n("Delete word") + } + } + } + } + } + } + } + + Component { + id: mobileSheet + Kirigami.OverlaySheet { + required property Sonnet.Settings settings + id: dictionarySheet + + header: SheetHeader {} + + ListView { + implicitWidth: Kirigami.Units.gridUnit * 15 + model: settings.currentIgnoreList + delegate: Kirigami.BasicListItem { + label: model.modelData + trailing: QQC2.ToolButton { + icon.name: "delete" + onClicked: { + remove(modelData) + if (instantApply) { + settings.save(); + } + } + QQC2.ToolTip { + text: i18n("Delete word") + } + } + } + } + } + } + + footer: QQC2.ToolBar { + visible: !instantApply + height: visible ? implicitHeight : 0 + contentItem: RowLayout { + Item { + Layout.fillWidth: true + } + + QQC2.Button { + text: i18n("Apply") + enabled: settings.modified + onClicked: settings.save(); + } + } + } + + function add(word) { + const dictionary = settings.currentIgnoreList; + dictionary.push(word); + settings.currentIgnoreList = dictionary; + } + + function remove(word) { + settings.currentIgnoreList = settings.currentIgnoreList.filter(function (value, _, _) { + return value !== word; + }); + } +} diff --git a/imports/NeoChat/Settings/qmldir b/imports/NeoChat/Settings/qmldir index 3baec9c71..6e25565d7 100644 --- a/imports/NeoChat/Settings/qmldir +++ b/imports/NeoChat/Settings/qmldir @@ -1,3 +1,4 @@ module NeoChat.Settings ThemeRadioButton 1.0 ThemeRadioButton.qml SettingsPage 1.0 SettingsPage.qml +SonnetConfigPage 1.0 SonnetConfigPage.qml diff --git a/res.qrc b/res.qrc index b5686417f..a0c2767f2 100644 --- a/res.qrc +++ b/res.qrc @@ -77,6 +77,7 @@ imports/NeoChat/Settings/AccountsPage.qml imports/NeoChat/Settings/DevicesPage.qml imports/NeoChat/Settings/About.qml + imports/NeoChat/Settings/SonnetConfigPage.qml imports/NeoChat/Settings/qmldir