Port SpellChecking setting page to mobileform

This commit is contained in:
Carl Schwan
2023-04-22 10:30:39 +02:00
parent fc1dc5c1d6
commit 2fb4fdd18f

View File

@@ -7,338 +7,208 @@ import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigami 2.15 as Kirigami
import org.kde.sonnet 1.0 as Sonnet import org.kde.sonnet 1.0 as Sonnet
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
Kirigami.Page { Kirigami.ScrollablePage {
id: 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.<br /> 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 { ColumnLayout {
anchors.fill: parent MobileForm.FormCard {
id: card
Kirigami.FormLayout { Sonnet.Settings {
Layout.fillWidth: true id: settings
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.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.fillWidth: true
Layout.leftMargin: wideMode ? 0 : Kirigami.Units.largeSpacing
Layout.rightMargin: wideMode ? 0 : Kirigami.Units.largeSpacing
}
QQC2.ScrollView { contentItem: ColumnLayout {
id: scroll spacing: 0
Layout.fillWidth: true MobileForm.FormCardHeader {
Layout.fillHeight: true title: i18n("Spellchecking")
enabled: autodetectLanguageCheckbox.checked }
Component.onCompleted: background.visible = wideMode
// HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) MobileForm.FormCheckDelegate {
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff id: enable
checked: settings.checkerEnabledByDefault
ListView { text: i18n("Enable automatic spell checking")
clip: true onCheckedChanged: {
model: settings.dictionaryModel settings.checkerEnabledByDefault = checked;
delegate: Kirigami.CheckableListItem { settings.save();
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 { MobileForm.FormDelegateSeparator { below: enable; above: skipUppercase }
QQC2.TextField {
id: dictionaryField MobileForm.FormCheckDelegate {
Layout.fillWidth: true id: skipUppercase
placeholderText: i18n("Add a new word to your personal dictionary…") checked: settings.skipUppercase
} text: i18n("Ignore uppercase words")
QQC2.Button { onCheckedChanged: {
text: i18nc("@action:button", "Add word") settings.skipUppercase = checked;
icon.name: "list-add" settings.save();
enabled: dictionaryField.text.length > 0 }
onClicked: {
add(dictionaryField.text);
dictionaryField.clear();
if (instantApply) {
settings.save();
} }
}
Layout.rightMargin: Kirigami.Units.largeSpacing
}
}
Component { MobileForm.FormDelegateSeparator { below: skipUppercase; above: skipRunTogether }
id: desktopSheet
QQC2.ApplicationWindow { MobileForm.FormCheckDelegate {
id: window id: skipRunTogether
required property Sonnet.Settings settings checked: settings.skipRunTogether
title: i18n("Spell checking dictionary") text: i18n("Ignore hyphenated words")
width: Kirigami.Units.gridUnit * 20 onCheckedChanged: {
height: Kirigami.Units.gridUnit * 20 settings.skipRunTogether = checked;
flags: Qt.Dialog | Qt.WindowCloseButtonHint settings.save();
header: Kirigami.AbstractApplicationHeader { }
leftPadding: Kirigami.Units.smallSpacing
rightPadding: Kirigami.Units.smallSpacing
contentItem: SheetHeader {
anchors.fill: parent
} }
}
QQC2.ScrollView {
anchors.fill: parent
// HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) MobileForm.FormDelegateSeparator { below: skipRunTogether; above: autodetectLanguageCheckbox }
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
ListView { MobileForm.FormCheckDelegate {
model: settings.currentIgnoreList id: autodetectLanguageCheckbox
delegate: Kirigami.BasicListItem { checked: settings.autodetectLanguage
label: model.modelData text: i18n("Detect language automatically")
trailing: QQC2.ToolButton { onCheckedChanged: {
icon.name: "delete" settings.autodetectLanguage = checked;
onClicked: { settings.save();
remove(modelData) }
if (instantApply) { }
settings.save();
MobileForm.FormDelegateSeparator { below: autodetectLanguageCheckbox; above: selectedDefaultLanguage }
MobileForm.FormComboBoxDelegate {
id: selectedDefaultLanguage
text: i18n("Selected default language:")
model: isEmpty ? [{"display": i18n("None")}] : settings.dictionaryModel
textRole: "display"
displayMode: Kirigami.Settings.isMobile ? MobileForm.FormComboBoxDelegate.Dialog : MobileForm.FormComboBoxDelegate.Page
valueRole: "languageCode"
property bool isEmpty: false
Component.onCompleted: {
if (settings.dictionaryModel.rowCount() === 0) {
isEmpty = true;
} else {
currentIndex = indexOfValue(settings.defaultLanguage);
}
}
onActivated: settings.defaultLanguage = currentValue;
}
MobileForm.FormDelegateSeparator { below: selectedDefaultLanguage; above: spellCheckingLanguage }
MobileForm.FormButtonDelegate {
id: spellCheckingLanguage
text: i18n("Additional spell checking languages")
description: i18n("%1 will provide spell checking and suggestions for the languages listed here when autodetection is enabled.", Qt.application.displayName)
enabled: autodetectLanguageCheckbox.checked
onClicked: pageStack.pushDialogLayer(spellCheckingLanguageList, {}, {
width: pageStack.width - Kirigami.Units.gridUnit * 5,
height: pageStack.height - Kirigami.Units.gridUnit * 5,
})
}
MobileForm.FormDelegateSeparator { below: spellCheckingLanguageList; above: personalDictionary }
MobileForm.FormButtonDelegate {
id: personalDictionary
text: i18n("Open Personal Dictionary")
onClicked: pageStack.pushDialogLayer(dictionaryPage, {}, {
width: pageStack.width - Kirigami.Units.gridUnit * 5,
height: pageStack.height - Kirigami.Units.gridUnit * 5,
})
}
Component {
id: spellCheckingLanguageList
Kirigami.ScrollablePage {
id: scroll
title: i18nc("@title:window", "Spell checking languages")
ListView {
clip: true
model: settings.dictionaryModel
delegate: Kirigami.CheckableListItem {
label: model.display
action: Kirigami.Action {
onTriggered: model.checked = checked
}
Accessible.description: model.isDefault ? i18n("Default Language") : ''
checked: model.checked
trailing: Kirigami.Icon {
source: "favorite"
visible: model.isDefault
HoverHandler {
id: hover
}
QQC2.ToolTip {
visible: hover.hovered
text: i18n("Default Language")
}
} }
} }
QQC2.ToolTip { }
text: i18n("Delete word") }
}
}
Component {
id: dictionaryPage
Kirigami.ScrollablePage {
title: i18n("Spell checking dictionary")
footer: QQC2.ToolBar {
contentItem: RowLayout {
QQC2.TextField {
id: dictionaryField
Layout.fillWidth: true
Accessible.name: placeholderText
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
}
}
}
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 { function add(word: string) {
id: mobileSheet const dictionary = settings.currentIgnoreList;
Kirigami.OverlaySheet { dictionary.push(word);
required property Sonnet.Settings settings settings.currentIgnoreList = dictionary;
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 { function remove(word: string) {
text: i18n("Apply") settings.currentIgnoreList = settings.currentIgnoreList.filter((value, _, _) => {
enabled: settings.modified return value !== word;
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;
});
}
} }