From 8bce5a05c950a2429f1dbb73706b6f5207d413c4 Mon Sep 17 00:00:00 2001 From: Cyril Jacquet Date: Sat, 30 Apr 2022 13:31:53 +0200 Subject: [PATCH 1/3] fix spellchecker fix " 's " showing as mispelled on user dict words with english fix behavior of add user dict word dialog fix refresh of text highlighting when adding word or changing dict language --- src/app/src/qml/Commons/WritingZone.qml | 358 +++++++++++------------ src/app/src/skrrootitem.cpp | 4 +- src/app/src/skrspellchecker.cpp | 43 ++- src/app/src/skrspellchecker.h | 2 +- src/plugins/projectPage/UserDictPage.qml | 124 ++++---- src/translations/skribisto_en_US.ts | 10 +- 6 files changed, 268 insertions(+), 273 deletions(-) diff --git a/src/app/src/qml/Commons/WritingZone.qml b/src/app/src/qml/Commons/WritingZone.qml index 1beed23ef..0883a0b12 100755 --- a/src/app/src/qml/Commons/WritingZone.qml +++ b/src/app/src/qml/Commons/WritingZone.qml @@ -40,7 +40,7 @@ WritingZoneForm { } property string placeholderText: "" onPlaceholderTextChanged: { - textArea.placeholderText = placeholderText + textArea.placeholderText = placeholderText } // clipboard : SKRClipboard { @@ -60,36 +60,37 @@ WritingZoneForm { property bool active: false onActiveChanged: { + //console.log("active",active ) } - Timer{ + Timer { id: deactivateTimer interval: 200 onTriggered: { root.active = false } } - //------------------------------------------------- + //------------------------------------------------- property int contentY: 0 - Binding{ - when: !active || leftScrollFlickable.active || rightScrollFlickable.active + Binding { + when: !active || leftScrollFlickable.active + || rightScrollFlickable.active target: flickable property: "contentY" value: root.contentY restoreMode: Binding.RestoreNone - } - Binding{ - when: active && !leftScrollFlickable.active && !rightScrollFlickable.active + Binding { + when: active && !leftScrollFlickable.active + && !rightScrollFlickable.active target: root property: "contentY" value: flickable.contentY restoreMode: Binding.RestoreNone - } //------------------------------------------------- @@ -216,7 +217,7 @@ WritingZoneForm { //----------------------------------------------------------- // ---------context menu :---------------------------------- //----------------------------------------------------------- - textArea.onPressed: function(event) { + textArea.onPressed: function (event) { if (event.buttons === Qt.RightButton) { callTextAreaContextMenu(event.x, event.y) } @@ -584,7 +585,6 @@ WritingZoneForm { SkrSettings.spellCheckingSettings.onSpellCheckingActivationChanged.connect( determineSpellCheckerActivation) determineSpellCheckerActivation() - } } Component.onDestruction: { @@ -627,9 +627,13 @@ WritingZoneForm { } function determineSpellCheckerActivation() { - var value = SkrSettings.spellCheckingSettings.spellCheckingActivation - highlighter.spellChecker.activate( - SkrSettings.spellCheckingSettings.spellCheckingActivation) + var activated = SkrSettings.spellCheckingSettings.spellCheckingActivation + + if (activated) { + highlighter.spellChecker.activate(false) + highlighter.spellChecker.activate(true) + } + highlighter.rehighlight() // needed to "shake" the highlighter @@ -663,7 +667,7 @@ WritingZoneForm { setProjectDictInSpellChecker(projectId) } - highlighter.rehighlight() + determineSpellCheckerActivation() //console.log("langCode :", langCode) } @@ -694,39 +698,29 @@ WritingZoneForm { } // scrollView : - - leftScrollFlickable.onActiveChanged: { - root.active = leftScrollFlickable.active + root.active = leftScrollFlickable.active } rightScrollFlickable.onActiveChanged: { root.active = rightScrollFlickable.active } - flickable.onContentYChanged:{ + flickable.onContentYChanged: { - if(textArea.active){ + if (textArea.active) { root.active = true - if(deactivateTimer.running){ + if (deactivateTimer.running) { deactivateTimer.stop() } deactivateTimer.start() } } - - - - - - - //-------------------------------------------------------------------------------- //--------Page Up/Down------------------------------------------------------------- //--------Text centering---------------------------------------------------------- //-------------------------------------------------------------------------------- - property alias contentYBehaviorEnabled: contentYBehavior.enabled textArea.viewHeight: flickable.height - textArea.topPadding - textArea.bottomPadding @@ -734,9 +728,8 @@ WritingZoneForm { target: textArea function onMoveViewYCalled(height, animationEnabled) { - root.active = true - if(deactivateTimer.running){ + if (deactivateTimer.running) { deactivateTimer.stop() } deactivateTimer.start() @@ -766,13 +759,10 @@ WritingZoneForm { flickable.contentY = flickable.contentHeight - textArea.viewHeight contentYBehavior.enabled = true return - } - else if(flickable.contentHeight < textArea.height){ + } else if (flickable.contentHeight < textArea.height) { return } - - // normal move flickable.contentY += value contentYBehavior.enabled = true @@ -797,7 +787,7 @@ WritingZoneForm { acceptedModifiers: Qt.NoModifier acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad target: leftScrollItem - onWheel: function(event) { + onWheel: function (event) { textArea.moveViewYCalled(-event.angleDelta.y / 2, false) } } @@ -807,7 +797,7 @@ WritingZoneForm { acceptedModifiers: Qt.NoModifier acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad target: rightScrollItem - onWheel: function(event) { + onWheel: function (event) { textArea.moveViewYCalled(-event.angleDelta.y / 2, false) } } @@ -817,160 +807,159 @@ WritingZoneForm { //-------------------------------------------------------------- //--------Highlighter--------------------------------------------- //-------------------------------------------------------------- -// property rect visibleRect: Qt.rect(0, 0, 0, 0) -// //-------------------------------------------------------------------------------- -// flickable.onContentYChanged: determineVisibleRect() - -// function determineVisibleRect() { -// visibleRect = Qt.rect(flickable.contentX, flickable.contentY, -// flickable.contentWidth, flickable.contentHeight) -// } - -// function paintUnderlineForSpellcheck(positionList, blockBegin, blockEnd, uniqueBlock) { -// if (paintUnderlineForSpellcheckTimer.running) { -// paintUnderlineForSpellcheckTimer.stop() -// } - -// paintUnderlineForSpellcheckTimer.positionList = positionList -// paintUnderlineForSpellcheckTimer.blockBegin = blockBegin -// paintUnderlineForSpellcheckTimer.blockEnd = blockEnd -// paintUnderlineForSpellcheckTimer.uniqueBlock = uniqueBlock -// paintUnderlineForSpellcheckTimer.start() -// } -// Timer { -// id: paintUnderlineForSpellcheckTimer -// property var positionList -// property int blockBegin -// property int blockEnd -// property bool uniqueBlock - -// interval: 20 -// onTriggered: { -// determineVisibleRect() -// canvas.positionList = positionList -// canvas.blockBegin = blockBegin -// canvas.blockEnd = blockEnd -// canvas.uniqueBlock = uniqueBlock -// canvas.requestPaint() -// } -// } - -// Connections { -// target: SkrSettings.spellCheckingSettings -// function onSpellCheckingActivationChanged() { -// canvas.spellcheckEnabled = SkrSettings.spellCheckingSettings.spellCheckingActivation -// if (canvas.available) { -// canvas.requestPaint() -// } -// } -// } - -// onVisibleRectChanged: { -// canvas.spellcheckEnabled = SkrSettings.spellCheckingSettings.spellCheckingActivation -// if (canvas.available) { -// canvas.requestPaint() -// } -// } - -// Canvas { -// id: canvas -// parent: scrollView -// anchors.fill: parent - -// //renderStrategy: Canvas.Immediate -// //renderTarget: Canvas.FramebufferObject -// property var positionList: [] -// property int blockBegin: -1 -// property int blockEnd: -1 -// property bool uniqueBlock: false -// property bool spellcheckEnabled: true - -// onPaint: { - -// var pointList = [] -// var charWidthList = [] -// var visiblePositionList = [] - -// //console.log(positionList) -// for (var i = 0; i < positionList.length; i++) { -// var position = positionList[i] -// var rectangle = textArea.positionToRectangle(position) - -// if (rectangle.y + rectangle.height > visibleRect.y -// && rectangle.y + rectangle.height < visibleRect.y + visibleRect.height) { -// visiblePositionList.push(position) -// } - -// // if(rectangle.height < font.pointSize){ -// // return -// } -// for (var j = 0; j < visiblePositionList.length; j++) { -// var position2 = visiblePositionList[j] -// var rectangle2 = textArea.positionToRectangle(position2) -// var nextRectangle = textArea.positionToRectangle(position2 + 1) -// pointList.push( -// Qt.point( -// rectangle2.x, -// rectangle2.y + rectangle2.height - visibleRect.y)) -// var charWidth = nextRectangle.x - rectangle2.x -// if (charWidth < 0) { -// charWidthList.push(charWidthList[charWidthList.lenght - 1]) -// } else { -// charWidthList.push(charWidth) -// } -// } - -// if (uniqueBlock) { -// var blockBeginRectangle = textArea.positionToRectangle( -// blockBegin) -// var blockEndRectangle = textArea.positionToRectangle(blockEnd) -// var blockRectangle = Qt.rect( -// 0, blockBeginRectangle.y - visibleRect.y, -// canvas.width, -// blockEndRectangle.y - blockBeginRectangle.y -// + blockBeginRectangle.height) -// } - -// var ctx = getContext("2d") -// ctx.setLineDash([2, 4]) -// ctx.strokeStyle = SkrTheme.spellcheck -// ctx.beginPath() - -// if (uniqueBlock) { -// ctx.clearRect(blockRectangle.x, blockRectangle.y, -// blockRectangle.width, blockRectangle.height) -// } else { -// ctx.clearRect(0, 0, canvas.width, canvas.height) -// } -// if (spellcheckEnabled) { -// for (var k = 0; k < pointList.length; k++) { -// var spellcheckPoint = pointList[k] - -// ctx.moveTo(spellcheckPoint.x, spellcheckPoint.y) -// ctx.lineTo(spellcheckPoint.x + charWidthList[k], -// spellcheckPoint.y) -// ctx.moveTo(spellcheckPoint.x, spellcheckPoint.y + 1) -// ctx.lineTo(spellcheckPoint.x + charWidthList[k], -// spellcheckPoint.y + 1) -// } - -// ctx.stroke() -// } -// } -// } + // property rect visibleRect: Qt.rect(0, 0, 0, 0) + // //-------------------------------------------------------------------------------- + // flickable.onContentYChanged: determineVisibleRect() + + // function determineVisibleRect() { + // visibleRect = Qt.rect(flickable.contentX, flickable.contentY, + // flickable.contentWidth, flickable.contentHeight) + // } + + // function paintUnderlineForSpellcheck(positionList, blockBegin, blockEnd, uniqueBlock) { + // if (paintUnderlineForSpellcheckTimer.running) { + // paintUnderlineForSpellcheckTimer.stop() + // } + + // paintUnderlineForSpellcheckTimer.positionList = positionList + // paintUnderlineForSpellcheckTimer.blockBegin = blockBegin + // paintUnderlineForSpellcheckTimer.blockEnd = blockEnd + // paintUnderlineForSpellcheckTimer.uniqueBlock = uniqueBlock + // paintUnderlineForSpellcheckTimer.start() + // } + // Timer { + // id: paintUnderlineForSpellcheckTimer + // property var positionList + // property int blockBegin + // property int blockEnd + // property bool uniqueBlock + + // interval: 20 + // onTriggered: { + // determineVisibleRect() + // canvas.positionList = positionList + // canvas.blockBegin = blockBegin + // canvas.blockEnd = blockEnd + // canvas.uniqueBlock = uniqueBlock + // canvas.requestPaint() + // } + // } + + // Connections { + // target: SkrSettings.spellCheckingSettings + // function onSpellCheckingActivationChanged() { + // canvas.spellcheckEnabled = SkrSettings.spellCheckingSettings.spellCheckingActivation + // if (canvas.available) { + // canvas.requestPaint() + // } + // } + // } + + // onVisibleRectChanged: { + // canvas.spellcheckEnabled = SkrSettings.spellCheckingSettings.spellCheckingActivation + // if (canvas.available) { + // canvas.requestPaint() + // } + // } + + // Canvas { + // id: canvas + // parent: scrollView + // anchors.fill: parent + + // //renderStrategy: Canvas.Immediate + // //renderTarget: Canvas.FramebufferObject + // property var positionList: [] + // property int blockBegin: -1 + // property int blockEnd: -1 + // property bool uniqueBlock: false + // property bool spellcheckEnabled: true + + // onPaint: { + + // var pointList = [] + // var charWidthList = [] + // var visiblePositionList = [] + + // //console.log(positionList) + // for (var i = 0; i < positionList.length; i++) { + // var position = positionList[i] + // var rectangle = textArea.positionToRectangle(position) + + // if (rectangle.y + rectangle.height > visibleRect.y + // && rectangle.y + rectangle.height < visibleRect.y + visibleRect.height) { + // visiblePositionList.push(position) + // } + + // // if(rectangle.height < font.pointSize){ + // // return + // } + // for (var j = 0; j < visiblePositionList.length; j++) { + // var position2 = visiblePositionList[j] + // var rectangle2 = textArea.positionToRectangle(position2) + // var nextRectangle = textArea.positionToRectangle(position2 + 1) + // pointList.push( + // Qt.point( + // rectangle2.x, + // rectangle2.y + rectangle2.height - visibleRect.y)) + // var charWidth = nextRectangle.x - rectangle2.x + // if (charWidth < 0) { + // charWidthList.push(charWidthList[charWidthList.lenght - 1]) + // } else { + // charWidthList.push(charWidth) + // } + // } + + // if (uniqueBlock) { + // var blockBeginRectangle = textArea.positionToRectangle( + // blockBegin) + // var blockEndRectangle = textArea.positionToRectangle(blockEnd) + // var blockRectangle = Qt.rect( + // 0, blockBeginRectangle.y - visibleRect.y, + // canvas.width, + // blockEndRectangle.y - blockBeginRectangle.y + // + blockBeginRectangle.height) + // } + + // var ctx = getContext("2d") + // ctx.setLineDash([2, 4]) + // ctx.strokeStyle = SkrTheme.spellcheck + // ctx.beginPath() + + // if (uniqueBlock) { + // ctx.clearRect(blockRectangle.x, blockRectangle.y, + // blockRectangle.width, blockRectangle.height) + // } else { + // ctx.clearRect(0, 0, canvas.width, canvas.height) + // } + // if (spellcheckEnabled) { + // for (var k = 0; k < pointList.length; k++) { + // var spellcheckPoint = pointList[k] + + // ctx.moveTo(spellcheckPoint.x, spellcheckPoint.y) + // ctx.lineTo(spellcheckPoint.x + charWidthList[k], + // spellcheckPoint.y) + // ctx.moveTo(spellcheckPoint.x, spellcheckPoint.y + 1) + // ctx.lineTo(spellcheckPoint.x + charWidthList[k], + // spellcheckPoint.y + 1) + // } + + // ctx.stroke() + // } + // } + // } //focus : onActiveFocusChanged: { if (activeFocus) { - if(priv.forceActiveFocusEnabled){ + if (priv.forceActiveFocusEnabled) { textArea.forceActiveFocus() } - } else { } } - QtObject{ + QtObject { id: priv property bool forceActiveFocusEnabled: true } @@ -982,9 +971,8 @@ WritingZoneForm { findPanel.highlighter: documentHandler.highlighter findPanel.textArea: textArea - - function showFindPanel(){ - if(textArea.selectedText.length > 0){ + function showFindPanel() { + if (textArea.selectedText.length > 0) { findPanel.stringToFind = textArea.selectedText } @@ -994,7 +982,6 @@ WritingZoneForm { priv.forceActiveFocusEnabled = true } - Action { id: findAction enabled: root.activeFocus @@ -1006,4 +993,3 @@ WritingZoneForm { } } } - diff --git a/src/app/src/skrrootitem.cpp b/src/app/src/skrrootitem.cpp index f5ee859ed..b9c23146f 100755 --- a/src/app/src/skrrootitem.cpp +++ b/src/app/src/skrrootitem.cpp @@ -221,8 +221,8 @@ QString SKRRootItem::getWritableAddonsPathsListDir() const { QString SKRRootItem::cleanUpHtml(const QString& html) { // QString text = html; - qDebug() << "§§§§§§§§§§§§§§§§§§§§§§§§"; - qDebug() << "pre" << html; + //qDebug() << "§§§§§§§§§§§§§§§§§§§§§§§§"; + //qDebug() << "pre" << html; QTextDocument doc; diff --git a/src/app/src/skrspellchecker.cpp b/src/app/src/skrspellchecker.cpp index 4e06d2526..8effb2899 100755 --- a/src/app/src/skrspellchecker.cpp +++ b/src/app/src/skrspellchecker.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -183,16 +184,29 @@ QStringList SKRSpellChecker::suggest(const QString& word) // NOTE maybe useless void SKRSpellChecker::ignoreWord(const QString& word) { - addWordToDict(word); + addWordToDict(word, ""); } -void SKRSpellChecker::addWordToDict(const QString& word) +void SKRSpellChecker::addWordToDict(const QString& word, const QString& affix) { if (word == "") return; - if (m_encodingFix == "latin1") m_hunspell->add(word.toLatin1().toStdString()); + qDebug() << "word added to user dict" << word << affix; - if (m_encodingFix == "utf8") m_hunspell->add(word.toUtf8().toStdString()); + if(affix.isEmpty()){ + + if (m_encodingFix == "latin1") m_hunspell->add(word.toLatin1().toStdString()); + + if (m_encodingFix == "utf8") m_hunspell->add(word.toUtf8().toStdString()); + + } + else{ + + if (m_encodingFix == "latin1") m_hunspell->add_with_affix(word.toLatin1().toStdString(), affix.toLatin1().toStdString()); + + if (m_encodingFix == "utf8") m_hunspell->add_with_affix(word.toUtf8().toStdString(), affix.toUtf8().toStdString()); + + } } // --------------------------------------------------------------------------------- @@ -204,7 +218,25 @@ void SKRSpellChecker::addWordToUserDict(const QString& word, bool emitSignal) return; } - addWordToDict(word); + QString affix = ""; + qDebug() << "m_langCode" << m_langCode; + if(m_langCode.contains("en")){ + affix = "M"; + } + + + addWordToDict(word, affix); + std::vector stringVector = m_hunspell->suffix_suggest(word.toUtf8().toStdString()); + QList stringList; + stringList.reserve(stringVector.size()); + std::copy(stringVector.begin(), stringVector.end(), std::back_inserter(stringList)); + + QStringList suffixList; + for(const std::string &str : stringList){ + qDebug()<< "suffix_suggest" << QString::fromStdString(str); + } + + if (!m_userDict.contains(word)) { m_userDict.append(word); @@ -394,6 +426,7 @@ void SKRSpellChecker::setLangCode(const QString& newLangCode) qWarning() << QString("Dict %1 not found, using en_US").arg(newLangCode); } this->setDict(dictPath); + m_langCode = newLangCode; emit langCodeChanged(newLangCode); diff --git a/src/app/src/skrspellchecker.h b/src/app/src/skrspellchecker.h index b52732752..6b2bfca44 100755 --- a/src/app/src/skrspellchecker.h +++ b/src/app/src/skrspellchecker.h @@ -86,7 +86,7 @@ class SKRSpellChecker : public QObject { // fix bug when hunspell gives me latin1 encoded results on several Linux // systems : QString testHunspellForEncoding(); - void addWordToDict(const QString& word); + void addWordToDict(const QString& word, const QString &affix); Hunspell *m_hunspell; bool m_isActive, m_hunspellLaunched; QStringList m_userDict; diff --git a/src/plugins/projectPage/UserDictPage.qml b/src/plugins/projectPage/UserDictPage.qml index bcba3080d..eb31f4d43 100644 --- a/src/plugins/projectPage/UserDictPage.qml +++ b/src/plugins/projectPage/UserDictPage.qml @@ -8,7 +8,6 @@ import "../../../../Items" import "../../../../Commons" import "../../../.." - UserDictPageForm { id: root @@ -21,18 +20,16 @@ UserDictPageForm { Connections { target: skrData.projectDictHub() function onProjectDictFullyChanged(projectId, projectDictList) { - if(root.projectId === projectId){ + if (root.projectId === projectId) { populateList() } } } - - Connections { target: skrData.projectDictHub() function onProjectDictWordAdded(projectId, newWord) { - if(root.projectId === projectId){ + if (root.projectId === projectId) { populateList() } } @@ -41,7 +38,7 @@ UserDictPageForm { Connections { target: skrData.projectDictHub() function onProjectDictWordRemoved(projectId, wordToRemove) { - if(root.projectId === projectId){ + if (root.projectId === projectId) { populateList() } } @@ -53,12 +50,15 @@ UserDictPageForm { listView.model: listModel - function populateList(){ + function populateList() { listModel.clear() - var dictList = skrData.projectDictHub().getProjectDictList(root.projectId) + var dictList = skrData.projectDictHub().getProjectDictList( + root.projectId) - dictList.forEach(word => listModel.append({"word": word})) + dictList.forEach(word => listModel.append({ + "word": word + })) } listView.delegate: Component { @@ -68,9 +68,6 @@ UserDictPageForm { height: 30 focus: true - - - Accessible.name: model.word Accessible.role: Accessible.ListItem @@ -88,7 +85,7 @@ UserDictPageForm { // delegateRoot.forceActiveFocus() // eventPoint.accepted = true // } - onSingleTapped: function(eventPoint) { + onSingleTapped: function (eventPoint) { //create relationship with note listView.currentIndex = model.index delegateRoot.forceActiveFocus() @@ -97,18 +94,11 @@ UserDictPageForm { eventPoint.accepted = true } - - onGrabChanged: function(transition, point) { + onGrabChanged: function (transition, point) { point.accepted = false } - - } - - - - SkrLabel { text: model.word anchors.fill: parent @@ -116,16 +106,15 @@ UserDictPageForm { anchors.rightMargin: 3 horizontalAlignment: Qt.AlignLeft verticalAlignment: Qt.AlignVCenter - } } } - listView.highlight: Component { + listView.highlight: Component { id: highlight Rectangle { radius: 5 - border.color: SkrTheme.accent + border.color: SkrTheme.accent border.width: 2 visible: listView.activeFocus Behavior on y { @@ -139,50 +128,47 @@ UserDictPageForm { } } - listView.onActiveFocusChanged: { - if(activeFocus){ - if(listView.count > 0){ + if (activeFocus) { + if (listView.count > 0) { listView.itemAtIndex(0).forceActiveFocus() } } - } - - Action { id: addWordAction text: qsTr("Add word to dictionary") icon.source: "qrc:///icons/backup/list-add.svg" onTriggered: { addWordToDProjectDictDialog.open() - } } addWordButton.action: addWordAction SKRSpellChecker { - id : spellChecker + id: spellChecker Component.onCompleted: { var lang = skrData.projectHub().getLangCode(root.projectId) - if(lang){ - spellChecker.setLangCode(skrData.projectHub().getLangCode(root.projectId)) - spellChecker.setUserDict(skrData.projectDictHub().getProjectDictList(root.projectId)) - - + if (lang) { + spellChecker.setLangCode(skrData.projectHub().getLangCode( + root.projectId)) + spellChecker.setUserDict(skrData.projectDictHub( + ).getProjectDictList( + root.projectId)) + } } } - } - - Connections{ + Connections { target: skrData.projectHub() - function onLangCodeChanged(projectId, newLang){ - if(projectId === root.projectId){ + function onLangCodeChanged(projectId, newLang) { + if (projectId === root.projectId) { spellChecker.setLangCode(newLang) - spellChecker.setUserDict(skrData.projectDictHub().getProjectDictList(root.projectId)) + spellChecker.setUserDict(skrData.projectDictHub( + ).getProjectDictList( + root.projectId)) } } } @@ -198,68 +184,63 @@ UserDictPageForm { Layout.fillWidth: true text: "" - onAccepted: { - if(spellChecker.spell(addWordTextField.text)){ - addWordToDProjectDictDialog.accept() - } - } - onTextChanged: { - if(!spellChecker.active){ + if (addWordTextField.text === "") { label.text = "" - - } - else if(spellChecker.spell(addWordTextField.text)){ + } else if (spellChecker.spell(addWordTextField.text)) { label.text = qsTr("Word already in dictionary") - } - else { + addWordToDProjectDictDialog.standardButtons = Dialog.Cancel + addWordToDProjectDictDialog.width = 401 + addWordToDProjectDictDialog.width = 400 + } else { label.text = "" + addWordToDProjectDictDialog.standardButtons = Dialog.Ok | Dialog.Cancel + addWordToDProjectDictDialog.width = 401 + addWordToDProjectDictDialog.width = 400 } } + + Keys.onReturnPressed: addWordToDProjectDictDialog.accept() + Keys.onEnterPressed: addWordToDProjectDictDialog.accept() + Keys.onEscapePressed: addWordToDProjectDictDialog.reject() } SkrLabel { id: label Layout.alignment: Qt.AlignCenter Layout.fillWidth: true - - } - } - standardButtons: Dialog.Ok | Dialog.Cancel + standardButtons: Dialog.Cancel onRejected: { addWordTextField.text = "" - } onDiscarded: { - addWordTextField.text = "" - } onAccepted: { - - skrData.projectDictHub().addWordToProjectDict(root.projectId, addWordTextField.text) + if (!spellChecker.spell(addWordTextField.text)) { + skrData.projectDictHub().addWordToProjectDict( + root.projectId, addWordTextField.text) + } addWordTextField.text = "" } onActiveFocusChanged: { - if(activeFocus){ + if (activeFocus) { addWordTextField.forceActiveFocus() } - } onOpened: { addWordTextField.text = "" addWordTextField.forceActiveFocus() } - } QtObject { @@ -267,19 +248,14 @@ UserDictPageForm { property string selectedWord: "" } - Action { id: removeWordAction text: qsTr("Remove word from dictionary") icon.source: "qrc:///icons/backup/list-remove.svg" onTriggered: { - skrData.projectDictHub().removeWordFromProjectDict(root.projectId, priv.selectedWord) + skrData.projectDictHub().removeWordFromProjectDict( + root.projectId, priv.selectedWord) } } removeWordButton.action: removeWordAction - - - - - } diff --git a/src/translations/skribisto_en_US.ts b/src/translations/skribisto_en_US.ts index 1804b3e9d..d89098e28 100644 --- a/src/translations/skribisto_en_US.ts +++ b/src/translations/skribisto_en_US.ts @@ -3706,22 +3706,22 @@ UserDictPage - + Add word to dictionary - + Add a word to the project dictionary - + Word already in dictionary - + Remove word from dictionary @@ -3820,7 +3820,7 @@ WritingZone - + Find From 712d6b2947c6b391f10201c5342167ff57777b2b Mon Sep 17 00:00:00 2001 From: Cyril Jacquet Date: Sun, 1 May 2022 00:45:07 +0200 Subject: [PATCH 2/3] add 2 themes --- src/app/src/themes.qrc | 2 + src/app/src/themes/snowblind.json | 31 +++ .../src/themes/the-answer-to-snowblind.json | 32 +++ src/plugins/themePage/ThemePage.qml | 192 ++++++------------ src/translations/skribisto_en_US.ts | 28 +-- 5 files changed, 146 insertions(+), 139 deletions(-) create mode 100644 src/app/src/themes/snowblind.json create mode 100644 src/app/src/themes/the-answer-to-snowblind.json diff --git a/src/app/src/themes.qrc b/src/app/src/themes.qrc index b446de836..9d124bebc 100755 --- a/src/app/src/themes.qrc +++ b/src/app/src/themes.qrc @@ -3,5 +3,7 @@ themes/default-light.json themes/space-opera-theme.json themes/default-dark.json + themes/the-answer-to-snowblind.json + themes/snowblind.json diff --git a/src/app/src/themes/snowblind.json b/src/app/src/themes/snowblind.json new file mode 100644 index 000000000..39aeaae13 --- /dev/null +++ b/src/app/src/themes/snowblind.json @@ -0,0 +1,31 @@ +{ + "colors": { + "accent": "#8bcecb", + "buttonBackground": "#D6D7D7", + "buttonForeground": "#000000", + "buttonIcon": "#000000", + "buttonIconDisabled": "#D6D7D7", + "divider": "#83d9d0", + "findHighlight": "#ffff00", + "listItemBackground": "#fbfbfb", + "mainTextAreaBackground": "#FFFFFF", + "mainTextAreaForeground": "#000000", + "menuBackground": "#ffffff", + "minimapFindHighlight": "#ffff00", + "minimapOtherHighlight_1": "#8bc34a", + "minimapOtherHighlight_2": "", + "minimapOtherHighlight_3": "", + "minimapSpellCheckHighlight": "#800000", + "otherHighlight_1": "", + "otherHighlight_2": "", + "otherHighlight_3": "", + "pageBackground": "#ffffff", + "pageToolBarBackground": "#e6e6e6", + "secondaryTextAreaBackground": "#ffffff", + "secondaryTextAreaForeground": "#000000", + "spellCheckHighlight": "#800000", + "toolBarBackground": "#b2d9d7" + }, + "isEditable": false, + "themeName": "Snowblind" +} diff --git a/src/app/src/themes/the-answer-to-snowblind.json b/src/app/src/themes/the-answer-to-snowblind.json new file mode 100644 index 000000000..6f0232e33 --- /dev/null +++ b/src/app/src/themes/the-answer-to-snowblind.json @@ -0,0 +1,32 @@ +{ + "colors": { + "": "", + "accent": "#b56c17", + "buttonBackground": "#0e0e0e", + "buttonForeground": "#b1b1b1", + "buttonIcon": "#e2e2e2", + "buttonIconDisabled": "#414141", + "divider": "#9a9996", + "findHighlight": "#ffff00", + "listItemBackground": "#525252", + "mainTextAreaBackground": "#282525", + "mainTextAreaForeground": "#deddda", + "menuBackground": "#313131", + "minimapFindHighlight": "#ffff00", + "minimapOtherHighlight_1": "#8bc34a", + "minimapOtherHighlight_2": "", + "minimapOtherHighlight_3": "", + "minimapSpellCheckHighlight": "#7f7f7f", + "otherHighlight_1": "", + "otherHighlight_2": "", + "otherHighlight_3": "", + "pageBackground": "#313131", + "pageToolBarBackground": "#404142", + "secondaryTextAreaBackground": "#282525", + "secondaryTextAreaForeground": "#deddda", + "spellCheckHighlight": "#e66100", + "toolBarBackground": "#4a4842" + }, + "isEditable": false, + "themeName": "The Answer to Snowblind" +} diff --git a/src/plugins/themePage/ThemePage.qml b/src/plugins/themePage/ThemePage.qml index daafff2ad..319b13638 100755 --- a/src/plugins/themePage/ThemePage.qml +++ b/src/plugins/themePage/ThemePage.qml @@ -9,8 +9,6 @@ import "../../../../Items" import "../../../../Commons" import "../../../.." - - ThemePageForm { id: root property string pageType: "THEME" @@ -22,15 +20,14 @@ ThemePageForm { populateColorPropertiesListModel() } Component.onDestruction: { - if(rootWindow.visibility !== Window.FullScreen){ - SkrTheme.setDistractionFree(false) - } + if (rootWindow.visibility !== Window.FullScreen) { + SkrTheme.setDistractionFree(false) + } } //-------------------------------------------------------- //---View buttons----------------------------------------- //-------------------------------------------------------- - viewButtons.viewManager: root.viewManager viewButtons.position: root.position @@ -38,16 +35,14 @@ ThemePageForm { skrWindowManager.addWindowForProjectIndependantPageType(root.pageType) } - viewButtons.onSplitCalled: function(position){ + viewButtons.onSplitCalled: function (position) { viewManager.loadProjectIndependantPageAt(root.pageType, position) } titleLabel.text: title - //------------------------------------------------------------- //-----theme list----------------------------------------------- //------------------------------------------------------------- - addThemeButton.icon.source: "qrc:///icons/backup/edit-copy.svg" addThemeButton.onClicked: { SkrTheme.duplicate(selectedTheme, qsTr("%1 (copy)".arg(selectedTheme))) @@ -55,59 +50,55 @@ ThemePageForm { } //-------------------------------------------------------- - - ListModel { id: themeListModel } themeListView.model: themeListModel - function populateThemeListModel(){ + function populateThemeListModel() { themeListModel.clear() var list = SkrTheme.getThemeList() list.sort() var i - for(i = 0 ; i < list.length ; i++) { + for (i = 0; i < list.length; i++) { var isEditable = SkrTheme.isThemeEditable(list[i]) var name = list[i] - themeListModel.append({"text": name, "isEditable": isEditable}) - - + themeListModel.append({ + "text": name, + "isEditable": isEditable + }) } } //-------------------------------------------------------- - readonly property string currentLightThemeName: SkrTheme.currentLightThemeName readonly property string currentDarkThemeName: SkrTheme.currentDarkThemeName readonly property string currentDistractionFreeThemeName: SkrTheme.currentDistractionFreeThemeName property string selectedTheme: "" - themeListView.delegate: SkrListItemPane { id: themeDelegateRoot height: 60 - anchors{ + anchors { left: Qt.isQtObject(parent) ? parent.left : undefined right: Qt.isQtObject(parent) ? parent.right : undefined } - TapHandler { id: themeTapHandler - onSingleTapped: function(eventPoint) { + onSingleTapped: function (eventPoint) { themeListView.currentIndex = model.index selectedTheme = model.text themeDelegateRoot.forceActiveFocus() eventPoint.accepted = true } - onDoubleTapped: function(eventPoint) { + onDoubleTapped: function (eventPoint) { //console.log("double tapped") themeListView.currentIndex = model.index selectedTheme = model.text @@ -116,28 +107,25 @@ ThemePageForm { } } - - contentItem: RowLayout { anchors.fill: parent - Rectangle { id: themeCurrentItemIndicator color: "lightsteelblue" Layout.fillHeight: true Layout.preferredWidth: 5 - visible: themeListView.currentIndex === model.index && themeListView.activeFocus + visible: themeListView.currentIndex === model.index + && themeListView.activeFocus } Rectangle { id: themeOpenedItemIndicator - color: SkrTheme.accent + color: SkrTheme.accent Layout.fillHeight: true Layout.preferredWidth: 5 visible: model.text === selectedTheme } - SkrLabel { id: themeNameLabel text: model.text @@ -149,10 +137,8 @@ ThemePageForm { Layout.fillWidth: true } - SkrToolButton { - Layout.preferredHeight: 40 Layout.preferredWidth: 40 @@ -170,62 +156,61 @@ ThemePageForm { } } - Item { id: stretcher3 Layout.minimumWidth: 50 } - SkrRoundButton{ + SkrRoundButton { id: lightButton display: AbstractButton.IconOnly - text: SkrTheme.currentLightThemeName === model.text ? qsTr("Light") : qsTr("Set as light theme") - icon{ - source: SkrTheme.currentLightThemeName === model.text ? "qrc:///icons/backup/color-picker-white.svg" : "" + text: SkrTheme.currentLightThemeName === model.text ? qsTr("Light") : qsTr( + "Set as light theme") + icon { + source: SkrTheme.currentLightThemeName + === model.text ? "qrc:///icons/backup/color-picker-white.svg" : "" color: "transparent" } - onClicked:{ + onClicked: { SkrTheme.currentLightThemeName = model.text - } } - SkrRoundButton{ + SkrRoundButton { id: darkButton display: AbstractButton.IconOnly - text: SkrTheme.currentDarkThemeName === model.text ? qsTr("Dark") : qsTr("Set as dark theme") + text: SkrTheme.currentDarkThemeName === model.text ? qsTr("Dark") : qsTr( + "Set as dark theme") icon { - source: SkrTheme.currentDarkThemeName === model.text ? "qrc:///icons/backup/color-picker-black.svg" : "" + source: SkrTheme.currentDarkThemeName + === model.text ? "qrc:///icons/backup/color-picker-black.svg" : "" color: "transparent" } - - onClicked:{ + onClicked: { SkrTheme.currentDarkThemeName = model.text } } - SkrRoundButton{ + SkrRoundButton { id: distractionFreeButton display: AbstractButton.IconOnly - text: SkrTheme.currentDistractionFreeThemeName === model.text ? qsTr("Distraction free") : qsTr("Set as distraction free theme") - icon.source: SkrTheme.currentDistractionFreeThemeName === model.text ? "qrc:///icons/backup/view-fullscreen.svg" : "" + text: SkrTheme.currentDistractionFreeThemeName + === model.text ? qsTr("Distraction free") : qsTr( + "Set as distraction free theme") + icon.source: SkrTheme.currentDistractionFreeThemeName + === model.text ? "qrc:///icons/backup/view-fullscreen.svg" : "" - onClicked:{ + onClicked: { SkrTheme.currentDistractionFreeThemeName = model.text - } - } - } } //------------------------------------------------------------- //----- rename theme -------------------------------------------- //------------------------------------------------------------- - - SimpleDialog { id: renameDialog property string name: "" @@ -237,21 +222,17 @@ ThemePageForm { onAccepted: { renameDialog.accept() } - } - standardButtons: Dialog.Ok | Dialog.Cancel + standardButtons: Dialog.Ok | Dialog.Cancel onRejected: { renameDialog.name = "" - } onDiscarded: { - renameDialog.name = "" - } onAccepted: { @@ -262,26 +243,22 @@ ThemePageForm { } onActiveFocusChanged: { - if(activeFocus){ + if (activeFocus) { contentItem.forceActiveFocus() } - } onOpened: { contentItem.forceActiveFocus() renameTextField.selectAll() } - } //------------------------------------------------------------- //----- remove theme -------------------------------------------- //------------------------------------------------------------- - //-------------------------------------------------------- - removeThemeButton.icon.source: "qrc:///icons/backup/edit-delete.svg" removeThemeButton.onClicked: { removeDialog.name = selectedTheme @@ -289,26 +266,22 @@ ThemePageForm { populateThemeListModel() } - SimpleDialog { id: removeDialog property string name: "" title: qsTr("Remove a theme") - text: qsTr("Do you really want to remove the theme \"%1\"?").arg(removeDialog.name) + text: qsTr("Do you really want to remove the theme \"%1\"?").arg( + removeDialog.name) - - standardButtons: Dialog.Ok | Dialog.Cancel + standardButtons: Dialog.Ok | Dialog.Cancel onRejected: { removeDialog.name = "" - } onDiscarded: { - removeDialog.name = "" - } onAccepted: { @@ -318,24 +291,20 @@ ThemePageForm { } onActiveFocusChanged: { - if(activeFocus){ + if (activeFocus) { contentItem.forceActiveFocus() } - } onOpened: { contentItem.forceActiveFocus() removeDialog.selectAll() } - } - //------------------------------------------------------------- //------color properties-------------------------------------------- //------------------------------------------------------------- - onSelectedThemeChanged: { SkrTheme.selectedThemeName = selectedTheme populateColorPropertiesListModel() @@ -347,68 +316,62 @@ ThemePageForm { } propertiesListView.model: colorPropertiesModel - function populateColorPropertiesListModel(){ + function populateColorPropertiesListModel() { colorPropertiesModel.clear() var propertyHumanNamesMap = SkrTheme.getPropertyHumanNames() var propertyValuesMap = SkrTheme.selectedColorsMap var list = [] - for(var name in propertyValuesMap) { + for (var name in propertyValuesMap) { list.push(name) } list.sort() - - //is editable ? var isEditable = SkrTheme.isThemeEditable(selectedTheme) - - for(var i in list) { + for (var i in list) { var exactName = list[i] - if(SkrTheme.changedColorsMap[exactName]){ - colorPropertiesModel.append({"text": propertyHumanNamesMap[exactName], "propertyExactName": exactName, "color": SkrTheme.changedColorsMap[exactName], "isEditable": isEditable}) - } - else{ - colorPropertiesModel.append({"text": propertyHumanNamesMap[exactName], "propertyExactName": exactName, "color": propertyValuesMap[exactName], "isEditable": isEditable}) - + if (SkrTheme.changedColorsMap[exactName]) { + colorPropertiesModel.append({ + "text": propertyHumanNamesMap[exactName], + "propertyExactName": exactName, + "color": SkrTheme.changedColorsMap[exactName], + "isEditable": isEditable + }) + } else { + colorPropertiesModel.append({ + "text": propertyHumanNamesMap[exactName], + "propertyExactName": exactName, + "color": propertyValuesMap[exactName], + "isEditable": isEditable + }) } - - } - - - - - - } - property string currentProperty: "" - propertiesListView.delegate: SkrPane { id: delegateRoot height: 60 - anchors{ + anchors { left: Qt.isQtObject(parent) ? parent.left : undefined right: Qt.isQtObject(parent) ? parent.right : undefined } - TapHandler { id: tapHandler - onSingleTapped: function(eventPoint) { + onSingleTapped: function (eventPoint) { propertiesListView.currentIndex = model.index delegateRoot.forceActiveFocus() eventPoint.accepted = true } - onDoubleTapped: function(eventPoint) { + onDoubleTapped: function (eventPoint) { //console.log("double tapped") propertiesListView.currentIndex = model.index currentProperty = model.propertyExactName @@ -416,7 +379,7 @@ ThemePageForm { colorCodeTextField.enabled = model.isEditable - if(model.isEditable){ + if (model.isEditable) { colorDialog.currentColor = model.color colorDialog.open() @@ -426,12 +389,9 @@ ThemePageForm { } } - - RowLayout { anchors.fill: parent - Rectangle { id: currentItemIndicator color: "lightsteelblue" @@ -447,7 +407,6 @@ ThemePageForm { visible: model.propertyExactName === currentProperty } - SkrLabel { id: colorPropertyLabel text: model.text @@ -467,12 +426,10 @@ ThemePageForm { color: model.color border.color: "black" border.width: 1 - } SkrToolButton { - Layout.preferredHeight: 40 Layout.preferredWidth: 40 @@ -493,39 +450,29 @@ ThemePageForm { colorDialog.open() } } - - } } - - - //------------------------------------------------------------------------- //-------Examples ---------------------------------------------------------- //------------------------------------------------------------------------- - - forceLightButton.onClicked:{ + forceLightButton.onClicked: { SkrTheme.forceCurrentColorMode(SKRThemes.Light) } - forceDarkButton.onClicked:{ + forceDarkButton.onClicked: { SkrTheme.forceCurrentColorMode(SKRThemes.Dark) } - forceDistractionFreeButton.onClicked:{ + forceDistractionFreeButton.onClicked: { SkrTheme.forceCurrentColorMode(SKRThemes.DistractionFree) } - primaryTextAreaSample.textArea.text: qsTr("Primary text %1").arg("erroor") - - - + primaryTextAreaSample.textArea.text: qsTr("Primary text") //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- - resetThemeButton.onClicked: { SkrTheme.resetColorProperties() populateColorPropertiesListModel() @@ -539,26 +486,21 @@ ThemePageForm { primaryTextAreaSample.textArea.width -= 1 } - //------------------------------------------------------------------------- //-------color picker---------------------------------------------------- //------------------------------------------------------------------------- - colorCodeTextField.onEditingFinished: { SkrTheme.setColorProperty(currentProperty, colorCodeTextField.text) populateColorPropertiesListModel() } - LabPlatform.ColorDialog { id: colorDialog - onAccepted: { var colorString = skrQMLTools.colorString(colorDialog.color) SkrTheme.setColorProperty(currentProperty, colorString) populateColorPropertiesListModel() } } - } diff --git a/src/translations/skribisto_en_US.ts b/src/translations/skribisto_en_US.ts index d89098e28..0221422e0 100644 --- a/src/translations/skribisto_en_US.ts +++ b/src/translations/skribisto_en_US.ts @@ -3442,13 +3442,13 @@ ThemePage - + Themes - + Edit color @@ -3458,57 +3458,57 @@ - + Light - + Dark - + Set as light theme - + Set as dark theme - + Set as distraction free theme - + Rename - + Rename a theme - + Remove a theme - + Do you really want to remove the theme "%1"? - - Primary text %1 + + Primary text - + Distraction free From 6d411aba02214d1a272bdc525bd1ba93cb8fc5af Mon Sep 17 00:00:00 2001 From: Cyril Jacquet Date: Sun, 1 May 2022 00:48:16 +0200 Subject: [PATCH 3/3] update NEWS.yml --- NEWS.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS.yml b/NEWS.yml index 5fe6750b3..d78773b4c 100644 --- a/NEWS.yml +++ b/NEWS.yml @@ -1,3 +1,11 @@ +Version: 1.9.42 +Date: 2022-05-01 +Type: stable +Description: +- "Add two themes" +- "Fix add project dict dialog behavior" +- "Fix english project dict words with 's" +--- Version: 1.9.41 Date: 2022-04-11 Type: stable