From 9204003f57d8e1227b5c1aeb6d33163e208424ad Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 20:09:51 +0200
Subject: [PATCH 1/9] Add some pyqtSlot decorators as they apparently improve
perforamce a tiny bit
---
nw/gui/elements/doceditor.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py
index 5ed52888..e4c95c6b 100644
--- a/nw/gui/elements/doceditor.py
+++ b/nw/gui/elements/doceditor.py
@@ -30,7 +30,7 @@ import nw
from time import time
-from PyQt5.QtCore import Qt, QTimer
+from PyQt5.QtCore import Qt, QTimer, pyqtSlot
from PyQt5.QtWidgets import (
qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox, QLabel
)
@@ -589,6 +589,7 @@ class GuiDocEditor(QTextEdit):
# Signals and Slots
##
+ @pyqtSlot(int, int, int)
def _docChange(self, thePos, charsRemoved, charsAdded):
"""Triggered by QTextDocument->contentsChanged. This also
triggers the syntax highlighter.
@@ -602,6 +603,7 @@ class GuiDocEditor(QTextEdit):
self._docAutoReplace(self.qDocument.findBlock(thePos))
return
+ @pyqtSlot("QPoint")
def _openContextMenu(self, thePos):
"""Triggered by right click to open the context menu. Also
triggered by the Ctrl+. shortcut.
@@ -663,6 +665,7 @@ class GuiDocEditor(QTextEdit):
self.hLight.rehighlightBlock(theCursor.block())
return
+ @pyqtSlot()
def _runCounter(self):
"""Decide whether to run the word counter, or stop the timer due
to inactivity.
@@ -678,6 +681,7 @@ class GuiDocEditor(QTextEdit):
self.wCounter.start()
return
+ @pyqtSlot()
def _updateCounts(self):
"""Slot for the word counter's finished signal
"""
@@ -730,6 +734,8 @@ class GuiDocEditor(QTextEdit):
return True
def _insertHardBreak(self):
+ """Inserts a hard line break at the cursor position.
+ """
theCursor = self.textCursor()
theCursor.beginEditBlock()
theCursor.insertText(" \n")
@@ -737,6 +743,8 @@ class GuiDocEditor(QTextEdit):
return
def _insertNonBreakingSpace(self):
+ """Inserts a non-breaking space at the cursor position.
+ """
theCursor = self.textCursor()
theCursor.beginEditBlock()
theCursor.insertText(nwUnicode.U_NBSP)
From 704d9a11e473890037017327c431adc7da503721 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 20:41:39 +0200
Subject: [PATCH 2/9] Merged the spell checking classes into one file
---
nw/gui/elements/doceditor.py | 2 +-
nw/tools/__init__.py | 4 +-
nw/tools/spellcheck.py | 168 ++++++++++++++++++++++++++++++++++-
nw/tools/spellenchant.py | 102 ---------------------
nw/tools/spellsimple.py | 129 ---------------------------
5 files changed, 170 insertions(+), 235 deletions(-)
delete mode 100644 nw/tools/spellenchant.py
delete mode 100644 nw/tools/spellsimple.py
diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py
index e4c95c6b..7681fe62 100644
--- a/nw/gui/elements/doceditor.py
+++ b/nw/gui/elements/doceditor.py
@@ -1007,7 +1007,7 @@ class GuiDocEditor(QTextEdit):
"""
if self.mainConf.spellTool == "enchant":
- from nw.tools.spellenchant import NWSpellEnchant
+ from nw.tools.spellcheck import NWSpellEnchant
self.theDict = NWSpellEnchant()
else:
self.theDict = NWSpellSimple()
diff --git a/nw/tools/__init__.py b/nw/tools/__init__.py
index d43736f9..14ddbc7c 100644
--- a/nw/tools/__init__.py
+++ b/nw/tools/__init__.py
@@ -4,8 +4,8 @@ from nw.tools.analyse import TextAnalysis
from nw.tools.legacy import projectMaintenance
from nw.tools.optionstate import OptionState
from nw.tools.spellcheck import NWSpellCheck
-from nw.tools.spellenchant import NWSpellEnchant
-from nw.tools.spellsimple import NWSpellSimple
+from nw.tools.spellcheck import NWSpellEnchant
+from nw.tools.spellcheck import NWSpellSimple
from nw.tools.translate import numberToWord
from nw.tools.wordcount import countWords
diff --git a/nw/tools/spellcheck.py b/nw/tools/spellcheck.py
index a5b534cd..f540fdc4 100644
--- a/nw/tools/spellcheck.py
+++ b/nw/tools/spellcheck.py
@@ -28,7 +28,8 @@
import logging
import nw
-from os import path
+from os import path, listdir
+from difflib import get_close_matches
from nw.constants import isoLanguage
@@ -108,3 +109,168 @@ class NWSpellCheck():
return
# END Class NWSpellCheck
+
+# ================================================================================================ #
+# Enchant Based SpellChecking
+# ================================================================================================ #
+
+class NWSpellEnchant(NWSpellCheck):
+
+ def __init__(self):
+ NWSpellCheck.__init__(self)
+ logger.debug("Enchant spell checking activated")
+ return
+
+ def setLanguage(self, theLang, projectDict=None):
+ """Load a dictionary for the language specified in the config.
+ If that fails, we load a dummy dictionary so that lookups don't
+ crash.
+ """
+ try:
+ import enchant
+ self.theDict = enchant.Dict(theLang)
+ self.spellLanguage = theLang
+ logger.debug("Enchant spell checking for language %s loaded" % theLang)
+ except:
+ logger.error("Failed to load enchant spell checking for language %s" % theLang)
+ self.theDict = NWSpellEnchantDummy()
+ self.spellLanguage = None
+
+ self._readProjectDictionary(projectDict)
+ for pWord in self.PROJW:
+ self.theDict.add_to_session(pWord)
+
+ return
+
+ def checkWord(self, theWord):
+ return self.theDict.check(theWord)
+
+ def suggestWords(self, theWord):
+ return self.theDict.suggest(theWord)
+
+ def addWord(self, newWord):
+ self.theDict.add_to_session(newWord)
+ NWSpellCheck.addWord(self, newWord)
+ return
+
+ def listDictionaries(self):
+ retList = []
+ for spTag, spProvider in enchant.list_dicts():
+ spName = "%s [%s]" % (self.expandLanguage(spTag), spProvider.name)
+ retList.append((spTag, spName))
+ return retList
+
+# END Class NWSpellEnchant
+
+class NWSpellEnchantDummy:
+
+ def __init__(self):
+ return
+
+ def check(self, theWord):
+ return True
+
+ def suggest(self, theWord):
+ return []
+
+ def add_to_session(self, theWord):
+ return
+
+# END Class NWSpellEnchantDummy
+
+# ================================================================================================ #
+# Fallback SpellChecking Using difflib
+# ================================================================================================ #
+
+class NWSpellSimple(NWSpellCheck):
+
+ WORDS = []
+
+ def __init__(self):
+ NWSpellCheck.__init__(self)
+ logger.debug("Simple spell checking activated")
+ return
+
+ def setLanguage(self, theLang, projectDict=None):
+
+ self.WORDS = []
+ dictFile = path.join(self.mainConf.dictPath,theLang+".dict")
+ try:
+ with open(dictFile,mode="r",encoding="utf-8") as wordsFile:
+ for theLine in wordsFile:
+ if len(theLine) == 0 or theLine.startswith("#"):
+ continue
+ self.WORDS.append(theLine.strip().lower())
+ logger.debug("Spell check word list for language %s loaded" % theLang)
+ logger.debug("Word list contains %d words" % len(self.WORDS))
+ self.spellLanguage = theLang
+ except Exception as e:
+ logger.error("Failed to load spell check word list for language %s" % theLang)
+ logger.error(str(e))
+ self.spellLanguage = None
+
+ self._readProjectDictionary(projectDict)
+ for pWord in self.PROJW:
+ if pWord not in self.WORDS:
+ self.WORDS.append(pWord)
+
+ return
+
+ def checkWord(self, theWord):
+ """Check if a word exists in the word list. Make sure to keep
+ this function as fast as possible as it is called for every
+ word by the syntax highlighter.
+ """
+ theWord = theWord.replace(self.mainConf.fmtApostrophe,"'").lower()
+ return theWord in self.WORDS
+
+ def suggestWords(self, theWord):
+ """Get suggestions for correct word from difflib, and make sure
+ the first character is upper case if that was also the case for
+ the word be3ing checked. Also make sure the apostrophe is
+ changed to the one in the dictionary, and then put back in the
+ results.
+ """
+ theWord = theWord.strip()
+ if len(theWord) == 0:
+ return []
+
+ firstUp = theWord[0] == theWord[0].upper()
+ theWord = theWord.lower()
+
+ theMatches = get_close_matches(theWord, self.WORDS, n=10, cutoff=0.75)
+ theOptions = []
+ for aWord in theMatches:
+ if len(aWord) == 0:
+ continue
+ if firstUp:
+ aWord = aWord[0].upper() + aWord[1:]
+ aWord = aWord.replace("'",self.mainConf.fmtApostrophe)
+ theOptions.append(aWord)
+
+ return theOptions
+
+ def addWord(self, newWord):
+ newWord = newWord.strip().lower()
+ if newWord not in self.WORDS:
+ self.WORDS.append(newWord)
+ NWSpellCheck.addWord(self, newWord)
+ return
+
+ def listDictionaries(self):
+
+ retList = []
+ for dictFile in listdir(self.mainConf.dictPath):
+
+ theBits = path.splitext(dictFile)
+ if len(theBits) != 2:
+ continue
+ if theBits[1] != ".dict":
+ continue
+
+ spName = "%s [Internal]" % self.expandLanguage(theBits[0])
+ retList.append((theBits[0], spName))
+
+ return retList
+
+# END Class NWSpellSimple
diff --git a/nw/tools/spellenchant.py b/nw/tools/spellenchant.py
deleted file mode 100644
index 4e7400a0..00000000
--- a/nw/tools/spellenchant.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# -*- coding: utf-8 -*-
-"""novelWriter Spell Check Wrapper : pyEnchant
-
- novelWriter – Spell Check Wrapper : pyEnchant
-===============================================
- Wrapper class for spell checking with pyEnchant
-
- File History:
- Created: 2019-06-11 [0.1.5]
-
- This file is a part of novelWriter
- Copyright 2020, Veronica Berglyd Olsen
-
- This program 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.
-
- This program 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 this program. If not, see .
-"""
-
-import logging
-import nw
-try:
- import enchant
-except:
- # No need to do anything
- # setLanguage will fall back to dummy dictionary
- pass
-
-from nw.tools.spellcheck import NWSpellCheck
-
-logger = logging.getLogger(__name__)
-
-class NWSpellEnchant(NWSpellCheck):
-
- def __init__(self):
- NWSpellCheck.__init__(self)
- logger.debug("Enchant spell checking activated")
- return
-
- def setLanguage(self, theLang, projectDict=None):
- """Load a dictionary for the language specified in the config.
- If that fails, we load a dummy dictionary so that lookups don't
- crash.
- """
- try:
- self.theDict = enchant.Dict(theLang)
- self.spellLanguage = theLang
- logger.debug("Enchant spell checking for language %s loaded" % theLang)
- except:
- logger.error("Failed to load enchant spell checking for language %s" % theLang)
- self.theDict = NWSpellEnchantDummy()
- self.spellLanguage = None
-
- self._readProjectDictionary(projectDict)
- for pWord in self.PROJW:
- self.theDict.add_to_session(pWord)
-
- return
-
- def checkWord(self, theWord):
- return self.theDict.check(theWord)
-
- def suggestWords(self, theWord):
- return self.theDict.suggest(theWord)
-
- def addWord(self, newWord):
- self.theDict.add_to_session(newWord)
- NWSpellCheck.addWord(self, newWord)
- return
-
- def listDictionaries(self):
- retList = []
- for spTag, spProvider in enchant.list_dicts():
- spName = "%s [%s]" % (self.expandLanguage(spTag), spProvider.name)
- retList.append((spTag, spName))
- return retList
-
-# END Class NWSpellEnchant
-
-class NWSpellEnchantDummy:
-
- def __init__(self):
- return
-
- def check(self, theWord):
- return True
-
- def suggest(self, theWord):
- return []
-
- def add_to_session(self, theWord):
- return
-
-# END Class NWSpellEnchantDummy
diff --git a/nw/tools/spellsimple.py b/nw/tools/spellsimple.py
deleted file mode 100644
index 63a8847b..00000000
--- a/nw/tools/spellsimple.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# -*- coding: utf-8 -*-
-"""novelWriter Spell Check Simple
-
- novelWriter – Spell Check Simple
-==================================
- Simple spell checker based on difflib
-
- File History:
- Created: 2019-06-11 [0.1.5]
-
- This file is a part of novelWriter
- Copyright 2020, Veronica Berglyd Olsen
-
- This program 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.
-
- This program 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 this program. If not, see .
-"""
-
-import logging
-import nw
-
-from os import path, listdir
-from difflib import get_close_matches
-
-logger = logging.getLogger(__name__)
-
-from nw.tools.spellcheck import NWSpellCheck
-
-class NWSpellSimple(NWSpellCheck):
-
- WORDS = []
-
- def __init__(self):
- NWSpellCheck.__init__(self)
- logger.debug("Simple spell checking activated")
- return
-
- def setLanguage(self, theLang, projectDict=None):
-
- self.WORDS = []
- dictFile = path.join(self.mainConf.dictPath,theLang+".dict")
- try:
- with open(dictFile,mode="r",encoding="utf-8") as wordsFile:
- for theLine in wordsFile:
- if len(theLine) == 0 or theLine.startswith("#"):
- continue
- self.WORDS.append(theLine.strip().lower())
- logger.debug("Spell check word list for language %s loaded" % theLang)
- logger.debug("Word list contains %d words" % len(self.WORDS))
- self.spellLanguage = theLang
- except Exception as e:
- logger.error("Failed to load spell check word list for language %s" % theLang)
- logger.error(str(e))
- self.spellLanguage = None
-
- self._readProjectDictionary(projectDict)
- for pWord in self.PROJW:
- if pWord not in self.WORDS:
- self.WORDS.append(pWord)
-
- return
-
- def checkWord(self, theWord):
- """Check if a word exists in the word list. Make sure to keep
- this function as fast as possible as it is called for every
- word by the syntax highlighter.
- """
- theWord = theWord.replace(self.mainConf.fmtApostrophe,"'").lower()
- return theWord in self.WORDS
-
- def suggestWords(self, theWord):
- """Get suggestions for correct word from difflib, and make sure
- the first character is upper case if that was also the case for
- the word be3ing checked. Also make sure the apostrophe is
- changed to the one in the dictionary, and then put back in the
- results.
- """
- theWord = theWord.strip()
- if len(theWord) == 0:
- return []
-
- firstUp = theWord[0] == theWord[0].upper()
- theWord = theWord.lower()
-
- theMatches = get_close_matches(theWord, self.WORDS, n=10, cutoff=0.75)
- theOptions = []
- for aWord in theMatches:
- if len(aWord) == 0:
- continue
- if firstUp:
- aWord = aWord[0].upper() + aWord[1:]
- aWord = aWord.replace("'",self.mainConf.fmtApostrophe)
- theOptions.append(aWord)
-
- return theOptions
-
- def addWord(self, newWord):
- newWord = newWord.strip().lower()
- if newWord not in self.WORDS:
- self.WORDS.append(newWord)
- NWSpellCheck.addWord(self, newWord)
- return
-
- def listDictionaries(self):
-
- retList = []
- for dictFile in listdir(self.mainConf.dictPath):
-
- theBits = path.splitext(dictFile)
- if len(theBits) != 2:
- continue
- if theBits[1] != ".dict":
- continue
-
- spName = "%s [Internal]" % self.expandLanguage(theBits[0])
- retList.append((theBits[0], spName))
-
- return retList
-
-# END Class NWSpellSimple
From 5cc036e125497d8cb0c25731c57ad3f7fa8e2e18 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 20:57:03 +0200
Subject: [PATCH 3/9] Fixed a bug in language lookup for enchant spelling
---
nw/tools/spellcheck.py | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/nw/tools/spellcheck.py b/nw/tools/spellcheck.py
index f540fdc4..fda4022d 100644
--- a/nw/tools/spellcheck.py
+++ b/nw/tools/spellcheck.py
@@ -35,6 +35,10 @@ from nw.constants import isoLanguage
logger = logging.getLogger(__name__)
+# ================================================================================================ #
+# SpellChecking SuperClass
+# ================================================================================================ #
+
class NWSpellCheck():
SP_INTERNAL = "internal"
@@ -155,9 +159,13 @@ class NWSpellEnchant(NWSpellCheck):
def listDictionaries(self):
retList = []
- for spTag, spProvider in enchant.list_dicts():
- spName = "%s [%s]" % (self.expandLanguage(spTag), spProvider.name)
- retList.append((spTag, spName))
+ try:
+ import enchant
+ for spTag, spProvider in enchant.list_dicts():
+ spName = "%s [%s]" % (self.expandLanguage(spTag), spProvider.name)
+ retList.append((spTag, spName))
+ except:
+ logger.error("Failed to list languages for enchant spell checking")
return retList
# END Class NWSpellEnchant
From 386020bcf816610ddb4e2fc3b7c6b56b433a19bb Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 20:58:34 +0200
Subject: [PATCH 4/9] Renamed 'project' folder to 'core'
---
nw/convert/tokenizer.py | 2 +-
nw/core/__init__.py | 11 +++++++++++
nw/{project => core}/document.py | 0
nw/{project => core}/index.py | 0
nw/{project => core}/project.py | 0
nw/gui/dialogs/docmerge.py | 2 +-
nw/gui/dialogs/docsplit.py | 2 +-
nw/gui/elements/doceditor.py | 2 +-
nw/gui/elements/doctree.py | 2 +-
nw/guimain.py | 2 +-
nw/project/__init__.py | 11 -----------
tests/test_item.py | 2 +-
tests/test_project.py | 4 ++--
13 files changed, 20 insertions(+), 20 deletions(-)
create mode 100644 nw/core/__init__.py
rename nw/{project => core}/document.py (100%)
rename nw/{project => core}/index.py (100%)
rename nw/{project => core}/project.py (100%)
delete mode 100644 nw/project/__init__.py
diff --git a/nw/convert/tokenizer.py b/nw/convert/tokenizer.py
index f891a9f7..59508d4c 100644
--- a/nw/convert/tokenizer.py
+++ b/nw/convert/tokenizer.py
@@ -32,7 +32,7 @@ import nw
from operator import itemgetter
from PyQt5.QtCore import QRegularExpression
-from nw.project.document import NWDoc
+from nw.core.document import NWDoc
from nw.tools.translate import numberToWord
from nw.constants import nwItemLayout
diff --git a/nw/core/__init__.py b/nw/core/__init__.py
new file mode 100644
index 00000000..8bc04dcd
--- /dev/null
+++ b/nw/core/__init__.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+
+from nw.core.document import NWDoc
+from nw.core.index import NWIndex
+from nw.core.project import NWProject
+
+__all__ = [
+ "NWDoc",
+ "NWIndex",
+ "NWProject",
+]
diff --git a/nw/project/document.py b/nw/core/document.py
similarity index 100%
rename from nw/project/document.py
rename to nw/core/document.py
diff --git a/nw/project/index.py b/nw/core/index.py
similarity index 100%
rename from nw/project/index.py
rename to nw/core/index.py
diff --git a/nw/project/project.py b/nw/core/project.py
similarity index 100%
rename from nw/project/project.py
rename to nw/core/project.py
diff --git a/nw/gui/dialogs/docmerge.py b/nw/gui/dialogs/docmerge.py
index 887e8b72..097f4217 100644
--- a/nw/gui/dialogs/docmerge.py
+++ b/nw/gui/dialogs/docmerge.py
@@ -34,7 +34,7 @@ from PyQt5.QtWidgets import (
QListWidget, QAbstractItemView, QListWidgetItem
)
from nw.constants import nwAlert, nwItemType
-from nw.project import NWDoc
+from nw.core import NWDoc
logger = logging.getLogger(__name__)
diff --git a/nw/gui/dialogs/docsplit.py b/nw/gui/dialogs/docsplit.py
index 55be4ee4..bfb4e8ee 100644
--- a/nw/gui/dialogs/docsplit.py
+++ b/nw/gui/dialogs/docsplit.py
@@ -34,7 +34,7 @@ from PyQt5.QtWidgets import (
QListWidget, QAbstractItemView, QListWidgetItem
)
from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout
-from nw.project import NWDoc
+from nw.core import NWDoc
logger = logging.getLogger(__name__)
diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py
index 7681fe62..f7d494e1 100644
--- a/nw/gui/elements/doceditor.py
+++ b/nw/gui/elements/doceditor.py
@@ -39,7 +39,7 @@ from PyQt5.QtGui import (
QTextDocument, QCursor
)
-from nw.project import NWDoc
+from nw.core import NWDoc
from nw.gui.tools import GuiDocHighlighter, WordCounter
from nw.gui.elements.doctitlebar import GuiDocTitleBar
from nw.tools import NWSpellSimple
diff --git a/nw/gui/elements/doctree.py b/nw/gui/elements/doctree.py
index 09330346..92a006de 100644
--- a/nw/gui/elements/doctree.py
+++ b/nw/gui/elements/doctree.py
@@ -34,7 +34,7 @@ from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QApplication, QMessageBox
)
-from nw.project import NWDoc
+from nw.core import NWDoc
from nw.constants import (
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert
)
diff --git a/nw/guimain.py b/nw/guimain.py
index 935c1fb2..4241c043 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -45,7 +45,7 @@ from nw.gui import (
GuiConfigEditor, GuiProjectEditor, GuiItemEditor, GuiProjectOutline,
GuiSessionLogView, GuiDocMerge, GuiDocSplit, GuiProjectLoad
)
-from nw.project import NWProject, NWDoc, NWIndex
+from nw.core import NWProject, NWDoc, NWIndex
from nw.tools import countWords
from nw.constants import nwFiles, nwItemType, nwAlert
diff --git a/nw/project/__init__.py b/nw/project/__init__.py
deleted file mode 100644
index f2a0fe0c..00000000
--- a/nw/project/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from nw.project.document import NWDoc
-from nw.project.index import NWIndex
-from nw.project.project import NWProject
-
-__all__ = [
- "NWDoc",
- "NWIndex",
- "NWProject",
-]
diff --git a/tests/test_item.py b/tests/test_item.py
index b58f1b7e..64268e62 100644
--- a/tests/test_item.py
+++ b/tests/test_item.py
@@ -9,7 +9,7 @@ from lxml import etree
from nwdummy import DummyMain
from nw.config import Config
-from nw.project.project import NWProject, NWItem
+from nw.core.project import NWProject, NWItem
from nw.constants import nwItemClass, nwItemType, nwItemLayout
theConf = Config()
diff --git a/tests/test_project.py b/tests/test_project.py
index c029fbba..7d920a37 100644
--- a/tests/test_project.py
+++ b/tests/test_project.py
@@ -10,8 +10,8 @@ from nwtools import *
from nwdummy import DummyMain
from nw.config import Config
-from nw.project.project import NWProject
-from nw.project.index import NWIndex
+from nw.core.project import NWProject
+from nw.core.index import NWIndex
from nw.constants import nwItemClass
theConf = Config()
From 9b049b6469fd7eab16896cc9a2707323b6129315 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 21:02:30 +0200
Subject: [PATCH 5/9] Moved spell checker classes to core folder
---
nw/core/__init__.py | 6 ++++++
nw/{tools => core}/spellcheck.py | 0
nw/gui/dialogs/configeditor.py | 2 +-
nw/gui/elements/doceditor.py | 4 ++--
nw/gui/statusbar.py | 2 +-
nw/tools/__init__.py | 6 ------
6 files changed, 10 insertions(+), 10 deletions(-)
rename nw/{tools => core}/spellcheck.py (100%)
diff --git a/nw/core/__init__.py b/nw/core/__init__.py
index 8bc04dcd..29ba7051 100644
--- a/nw/core/__init__.py
+++ b/nw/core/__init__.py
@@ -3,9 +3,15 @@
from nw.core.document import NWDoc
from nw.core.index import NWIndex
from nw.core.project import NWProject
+from nw.core.spellcheck import NWSpellCheck
+from nw.core.spellcheck import NWSpellEnchant
+from nw.core.spellcheck import NWSpellSimple
__all__ = [
"NWDoc",
"NWIndex",
"NWProject",
+ "NWSpellCheck",
+ "NWSpellEnchant",
+ "NWSpellSimple",
]
diff --git a/nw/tools/spellcheck.py b/nw/core/spellcheck.py
similarity index 100%
rename from nw/tools/spellcheck.py
rename to nw/core/spellcheck.py
diff --git a/nw/gui/dialogs/configeditor.py b/nw/gui/dialogs/configeditor.py
index ac0ed592..7a6f167b 100644
--- a/nw/gui/dialogs/configeditor.py
+++ b/nw/gui/dialogs/configeditor.py
@@ -39,7 +39,7 @@ from PyQt5.QtWidgets import (
)
from nw.additions import QSwitch, QConfigLayout
-from nw.tools import NWSpellCheck, NWSpellSimple, NWSpellEnchant
+from nw.core import NWSpellCheck, NWSpellSimple, NWSpellEnchant
from nw.constants import nwAlert, nwQuotes
logger = logging.getLogger(__name__)
diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py
index f7d494e1..a6d76958 100644
--- a/nw/gui/elements/doceditor.py
+++ b/nw/gui/elements/doceditor.py
@@ -42,7 +42,7 @@ from PyQt5.QtGui import (
from nw.core import NWDoc
from nw.gui.tools import GuiDocHighlighter, WordCounter
from nw.gui.elements.doctitlebar import GuiDocTitleBar
-from nw.tools import NWSpellSimple
+from nw.core import NWSpellSimple
from nw.constants import nwUnicode, nwDocAction
logger = logging.getLogger(__name__)
@@ -1007,7 +1007,7 @@ class GuiDocEditor(QTextEdit):
"""
if self.mainConf.spellTool == "enchant":
- from nw.tools.spellcheck import NWSpellEnchant
+ from nw.core.spellcheck import NWSpellEnchant
self.theDict = NWSpellEnchant()
else:
self.theDict = NWSpellSimple()
diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py
index f2492910..d815dd54 100644
--- a/nw/gui/statusbar.py
+++ b/nw/gui/statusbar.py
@@ -34,7 +34,7 @@ from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QColor, QPixmap, QFont
from PyQt5.QtWidgets import QStatusBar, QLabel
-from nw.tools import NWSpellCheck
+from nw.core import NWSpellCheck
logger = logging.getLogger(__name__)
diff --git a/nw/tools/__init__.py b/nw/tools/__init__.py
index 14ddbc7c..271db24c 100644
--- a/nw/tools/__init__.py
+++ b/nw/tools/__init__.py
@@ -3,9 +3,6 @@
from nw.tools.analyse import TextAnalysis
from nw.tools.legacy import projectMaintenance
from nw.tools.optionstate import OptionState
-from nw.tools.spellcheck import NWSpellCheck
-from nw.tools.spellcheck import NWSpellEnchant
-from nw.tools.spellcheck import NWSpellSimple
from nw.tools.translate import numberToWord
from nw.tools.wordcount import countWords
@@ -13,9 +10,6 @@ __all__ = [
"TextAnalysis",
"projectMaintenance",
"OptionState",
- "NWSpellCheck",
- "NWSpellEnchant",
- "NWSpellSimple",
"numberToWord",
"countWords",
]
From b0c71fb47da7f0d02ebc8d79f6d06e9ffd868b57 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 21:28:05 +0200
Subject: [PATCH 6/9] Removed the nw/tools folder and moved or merged the code
in elsewhere
---
{nw/tools => lib/text}/analyse.py | 0
nw/convert/tokenizer.py | 2 +-
nw/core/__init__.py | 6 +
nw/core/index.py | 2 +-
nw/core/project.py | 3 +-
nw/core/tools.py | 206 ++++++++++++++++++++++++++++++
nw/gui/__init__.py | 2 +
nw/gui/tools/__init__.py | 2 +
nw/{ => gui}/tools/optionstate.py | 0
nw/gui/tools/wordcounter.py | 2 +-
nw/guimain.py | 3 +-
nw/tools/__init__.py | 15 ---
nw/tools/legacy.py | 78 -----------
nw/tools/translate.py | 106 ---------------
nw/tools/wordcount.py | 76 -----------
15 files changed, 222 insertions(+), 281 deletions(-)
rename {nw/tools => lib/text}/analyse.py (100%)
create mode 100644 nw/core/tools.py
rename nw/{ => gui}/tools/optionstate.py (100%)
delete mode 100644 nw/tools/__init__.py
delete mode 100644 nw/tools/legacy.py
delete mode 100644 nw/tools/translate.py
delete mode 100644 nw/tools/wordcount.py
diff --git a/nw/tools/analyse.py b/lib/text/analyse.py
similarity index 100%
rename from nw/tools/analyse.py
rename to lib/text/analyse.py
diff --git a/nw/convert/tokenizer.py b/nw/convert/tokenizer.py
index 59508d4c..4ac99377 100644
--- a/nw/convert/tokenizer.py
+++ b/nw/convert/tokenizer.py
@@ -33,7 +33,7 @@ from operator import itemgetter
from PyQt5.QtCore import QRegularExpression
from nw.core.document import NWDoc
-from nw.tools.translate import numberToWord
+from nw.core.tools import numberToWord
from nw.constants import nwItemLayout
logger = logging.getLogger(__name__)
diff --git a/nw/core/__init__.py b/nw/core/__init__.py
index 29ba7051..a608acd7 100644
--- a/nw/core/__init__.py
+++ b/nw/core/__init__.py
@@ -6,6 +6,9 @@ from nw.core.project import NWProject
from nw.core.spellcheck import NWSpellCheck
from nw.core.spellcheck import NWSpellEnchant
from nw.core.spellcheck import NWSpellSimple
+from nw.core.tools import countWords
+from nw.core.tools import projectMaintenance
+from nw.core.tools import numberToWord
__all__ = [
"NWDoc",
@@ -14,4 +17,7 @@ __all__ = [
"NWSpellCheck",
"NWSpellEnchant",
"NWSpellSimple",
+ "countWords",
+ "projectMaintenance",
+ "numberToWord",
]
diff --git a/nw/core/index.py b/nw/core/index.py
index 9cc1098b..617ddb65 100644
--- a/nw/core/index.py
+++ b/nw/core/index.py
@@ -35,7 +35,7 @@ from time import time
from nw.constants import (
nwFiles, nwKeyWords, nwItemType, nwItemClass, nwItemLayout, nwAlert
)
-from nw.tools import countWords
+from nw.core.tools import countWords
logger = logging.getLogger(__name__)
diff --git a/nw/core/project.py b/nw/core/project.py
index fb4f340a..ef6558cf 100644
--- a/nw/core/project.py
+++ b/nw/core/project.py
@@ -40,7 +40,8 @@ from datetime import datetime
from time import time
from shutil import make_archive
-from nw.tools import projectMaintenance, OptionState
+from nw.gui.tools import OptionState
+from nw.core.tools import projectMaintenance
from nw.common import checkString, checkBool, checkInt
from nw.constants import (
nwFiles, nwConst, nwItemType, nwItemClass, nwItemLayout, nwAlert
diff --git a/nw/core/tools.py b/nw/core/tools.py
new file mode 100644
index 00000000..f90ae584
--- /dev/null
+++ b/nw/core/tools.py
@@ -0,0 +1,206 @@
+# -*- coding: utf-8 -*-
+"""novelWriter Word Counter
+
+ novelWriter – Word Counter
+============================
+ Simple word counter
+
+ File History:
+ Created: 2019-04-22 [0.0.1] countWords
+ Moved: 2019-05-30 [0.1.4] countWords
+ Created: 2020-02-13 [0.4.3] projectMaintenance
+
+ This file is a part of novelWriter
+ Copyright 2020, Veronica Berglyd Olsen
+
+ This program 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.
+
+ This program 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 this program. If not, see .
+"""
+
+import logging
+import nw
+
+from os import path, unlink, rmdir
+
+logger = logging.getLogger(__name__)
+
+def countWords(theText):
+ """Count words in a piece of text, skipping special syntax and
+ comments.
+ """
+
+ charCount = 0
+ wordCount = 0
+ paraCount = 0
+ prevEmpty = True
+
+ for aLine in theText.splitlines():
+
+ countPara = True
+ theLen = len(aLine)
+
+ if theLen == 0:
+ prevEmpty = True
+ continue
+ if aLine[0] == "@" or aLine[0] == "%":
+ continue
+
+ if aLine[0:5] == "#### ":
+ wordCount -= 1
+ charCount -= 5
+ countPara = False
+ elif aLine[0:4] == "### ":
+ wordCount -= 1
+ charCount -= 4
+ countPara = False
+ elif aLine[0:3] == "## ":
+ wordCount -= 1
+ charCount -= 3
+ countPara = False
+ elif aLine[0:2] == "# ":
+ wordCount -= 1
+ charCount -= 2
+ countPara = False
+
+ theBuff = aLine.replace("–"," ").replace("—"," ")
+ wordCount += len(theBuff.split())
+ charCount += theLen
+ if countPara and prevEmpty:
+ paraCount += 1
+ prevEmpty = countPara == False
+
+ return charCount, wordCount, paraCount
+
+def projectMaintenance(theProject):
+ """Wrapper class for handling various tasks related to managing old
+ projects with content from older versions of novelWriter.
+ """
+
+ # Remove no longer used project cache folder
+ if path.isdir(theProject.projPath):
+ cacheDir = path.join(theProject.projPath, "cache")
+ if path.isdir(cacheDir):
+ logger.info("Deprecated cache folder found")
+ rmList = []
+ for i in range(10):
+ rmList.append(path.join(cacheDir, "nwProject.nwx.%d" % i))
+ rmList.append(path.join(cacheDir, "projCount.txt"))
+ for rmFile in rmList:
+ if path.isfile(rmFile):
+ logger.info("Deleting: %s" % rmFile)
+ try:
+ unlink(rmFile)
+ except Exception as e:
+ logger.error(str(e))
+ logger.info("Deleting: %s" % cacheDir)
+ try:
+ rmdir(cacheDir)
+ except Exception as e:
+ logger.error(str(e))
+
+ # Remove no longer used meta files
+ rmList = []
+ rmList.append(path.join(theProject.projMeta, "mainOptions.json"))
+ rmList.append(path.join(theProject.projMeta, "exportOptions.json"))
+ rmList.append(path.join(theProject.projMeta, "outlineOptions.json"))
+ rmList.append(path.join(theProject.projMeta, "timelineOptions.json"))
+ rmList.append(path.join(theProject.projMeta, "docMergeOptions.json"))
+ rmList.append(path.join(theProject.projMeta, "sessionLogOptions.json"))
+ for rmFile in rmList:
+ if path.isfile(rmFile):
+ logger.info("Deleting: %s" % rmFile)
+ try:
+ unlink(rmFile)
+ except Exception as e:
+ logger.error(str(e))
+
+ return
+
+def numberToWord(numVal, theLanguage):
+ """Wrapper for converting numbers to words for chapter headings.
+ """
+ numWord = ""
+ if theLanguage == "en":
+ numWord = _numberToWordEN(numVal)
+ else:
+ numWord = _numberToWordEN(numVal)
+ # print("%4d : %s" % (numVal, numWord))
+ return numWord
+
+def _numberToWordEN(numVal):
+ """Convert numbers to English words.
+ """
+
+ numWord = ""
+ oneWord = ""
+ tenWord = ""
+ hunWord = ""
+
+ if numVal == 0:
+ return "Zero"
+
+ oneVal = numVal % 10
+ tenVal = (numVal-oneVal) % 100
+ hunVal = (numVal-tenVal-oneVal) % 1000
+
+ if hunVal == 100: hunWord = "One Hundred"
+ if hunVal == 200: hunWord = "Two Hundred"
+ if hunVal == 300: hunWord = "Three Hundred"
+ if hunVal == 400: hunWord = "Four Hundred"
+ if hunVal == 500: hunWord = "Five Hundred"
+ if hunVal == 600: hunWord = "Six Hundred"
+ if hunVal == 700: hunWord = "Seven Hundred"
+ if hunVal == 800: hunWord = "Eight Hundred"
+ if hunVal == 900: hunWord = "Nine Hundred"
+
+ if tenVal == 20: tenWord = "Twenty"
+ if tenVal == 30: tenWord = "Thirty"
+ if tenVal == 40: tenWord = "Forty"
+ if tenVal == 50: tenWord = "Fifty"
+ if tenVal == 60: tenWord = "Sixty"
+ if tenVal == 70: tenWord = "Seventy"
+ if tenVal == 80: tenWord = "Eighty"
+ if tenVal == 90: tenWord = "Ninety"
+
+ if tenVal == 10:
+ if oneVal == 0: oneWord = "Ten"
+ if oneVal == 1: oneWord = "Eleven"
+ if oneVal == 2: oneWord = "Twelve"
+ if oneVal == 3: oneWord = "Thirteen"
+ if oneVal == 4: oneWord = "Fourteen"
+ if oneVal == 5: oneWord = "Fifteen"
+ if oneVal == 6: oneWord = "Sixteen"
+ if oneVal == 7: oneWord = "Seventeen"
+ if oneVal == 8: oneWord = "Eighteen"
+ if oneVal == 9: oneWord = "Nineteen"
+ numWord = ("%s %s" % (hunWord, oneWord)).strip()
+ else:
+ if oneVal == 0: oneWord = ""
+ if oneVal == 1: oneWord = "One"
+ if oneVal == 2: oneWord = "Two"
+ if oneVal == 3: oneWord = "Three"
+ if oneVal == 4: oneWord = "Four"
+ if oneVal == 5: oneWord = "Five"
+ if oneVal == 6: oneWord = "Six"
+ if oneVal == 7: oneWord = "Seven"
+ if oneVal == 8: oneWord = "Eight"
+ if oneVal == 9: oneWord = "Nine"
+ if tenVal == 0:
+ numWord = ("%s %s" % (hunWord, oneWord)).strip()
+ else:
+ if oneVal == 0:
+ numWord = ("%s %s" % (hunWord, tenWord)).strip()
+ else:
+ numWord = ("%s %s-%s" % (hunWord, tenWord, oneWord)).strip()
+
+ return numWord
diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py
index d5f7e67b..a39d93ad 100644
--- a/nw/gui/__init__.py
+++ b/nw/gui/__init__.py
@@ -29,6 +29,7 @@ from nw.gui.elements.viewdetails import GuiDocViewDetails
# Tools
from nw.gui.tools.dochighlight import GuiDocHighlighter
+from nw.gui.tools.optionstate import OptionState
from nw.gui.tools.wordcounter import WordCounter
__all__ = [
@@ -54,5 +55,6 @@ __all__ = [
"GuiSearchBar",
"GuiDocViewDetails",
"GuiDocHighlighter",
+ "OptionState",
"WordCounter",
]
diff --git a/nw/gui/tools/__init__.py b/nw/gui/tools/__init__.py
index 4899f398..cc6cfdfa 100644
--- a/nw/gui/tools/__init__.py
+++ b/nw/gui/tools/__init__.py
@@ -1,9 +1,11 @@
# -*- coding: utf-8 -*-
from nw.gui.tools.dochighlight import GuiDocHighlighter
+from nw.gui.tools.optionstate import OptionState
from nw.gui.tools.wordcounter import WordCounter
__all__ = [
"GuiDocHighlighter",
+ "OptionState",
"WordCounter",
]
diff --git a/nw/tools/optionstate.py b/nw/gui/tools/optionstate.py
similarity index 100%
rename from nw/tools/optionstate.py
rename to nw/gui/tools/optionstate.py
diff --git a/nw/gui/tools/wordcounter.py b/nw/gui/tools/wordcounter.py
index b7cb2045..24a0b9ca 100644
--- a/nw/gui/tools/wordcounter.py
+++ b/nw/gui/tools/wordcounter.py
@@ -30,7 +30,7 @@ import nw
from PyQt5.QtCore import QThread
-from nw.tools.wordcount import countWords
+from nw.core.tools import countWords
logger = logging.getLogger(__name__)
diff --git a/nw/guimain.py b/nw/guimain.py
index 4241c043..b3356301 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -45,8 +45,7 @@ from nw.gui import (
GuiConfigEditor, GuiProjectEditor, GuiItemEditor, GuiProjectOutline,
GuiSessionLogView, GuiDocMerge, GuiDocSplit, GuiProjectLoad
)
-from nw.core import NWProject, NWDoc, NWIndex
-from nw.tools import countWords
+from nw.core import NWProject, NWDoc, NWIndex, countWords
from nw.constants import nwFiles, nwItemType, nwAlert
logger = logging.getLogger(__name__)
diff --git a/nw/tools/__init__.py b/nw/tools/__init__.py
deleted file mode 100644
index 271db24c..00000000
--- a/nw/tools/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from nw.tools.analyse import TextAnalysis
-from nw.tools.legacy import projectMaintenance
-from nw.tools.optionstate import OptionState
-from nw.tools.translate import numberToWord
-from nw.tools.wordcount import countWords
-
-__all__ = [
- "TextAnalysis",
- "projectMaintenance",
- "OptionState",
- "numberToWord",
- "countWords",
-]
diff --git a/nw/tools/legacy.py b/nw/tools/legacy.py
deleted file mode 100644
index b676caf7..00000000
--- a/nw/tools/legacy.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- coding: utf-8 -*-
-"""novelWriter Legacy Tools
-
- novelWriter – Legacy Tools
-============================
- Various functions to handle old projects
-
- File History:
- Created: 2020-02-13 [0.4.3]
-
- This file is a part of novelWriter
- Copyright 2020, Veronica Berglyd Olsen
-
- This program 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.
-
- This program 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 this program. If not, see .
-"""
-
-import logging
-import nw
-
-from os import path, unlink, rmdir
-
-logger = logging.getLogger(__name__)
-
-def projectMaintenance(theProject):
- """Wrapper class for handling various tasks related to managing old
- projects with content from older versions of novelWriter.
- """
-
- # Remove no longer used project cache folder
- if path.isdir(theProject.projPath):
- cacheDir = path.join(theProject.projPath, "cache")
- if path.isdir(cacheDir):
- logger.info("Deprecated cache folder found")
- rmList = []
- for i in range(10):
- rmList.append(path.join(cacheDir, "nwProject.nwx.%d" % i))
- rmList.append(path.join(cacheDir, "projCount.txt"))
- for rmFile in rmList:
- if path.isfile(rmFile):
- logger.info("Deleting: %s" % rmFile)
- try:
- unlink(rmFile)
- except Exception as e:
- logger.error(str(e))
- logger.info("Deleting: %s" % cacheDir)
- try:
- rmdir(cacheDir)
- except Exception as e:
- logger.error(str(e))
-
- # Remove no longer used meta files
- rmList = []
- rmList.append(path.join(theProject.projMeta, "mainOptions.json"))
- rmList.append(path.join(theProject.projMeta, "exportOptions.json"))
- rmList.append(path.join(theProject.projMeta, "outlineOptions.json"))
- rmList.append(path.join(theProject.projMeta, "timelineOptions.json"))
- rmList.append(path.join(theProject.projMeta, "docMergeOptions.json"))
- rmList.append(path.join(theProject.projMeta, "sessionLogOptions.json"))
- for rmFile in rmList:
- if path.isfile(rmFile):
- logger.info("Deleting: %s" % rmFile)
- try:
- unlink(rmFile)
- except Exception as e:
- logger.error(str(e))
-
- return
diff --git a/nw/tools/translate.py b/nw/tools/translate.py
deleted file mode 100644
index dd1f72f3..00000000
--- a/nw/tools/translate.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# -*- coding: utf-8 -*-
-"""novelWriter Translate Tools
-
- novelWriter – Translate Tools
-===============================
- Various translate tools
-
- File History:
- Created: 2019-10-13 [0.2.3]
-
- This file is a part of novelWriter
- Copyright 2020, Veronica Berglyd Olsen
-
- This program 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.
-
- This program 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 this program. If not, see .
-"""
-
-import logging
-import nw
-
-logger = logging.getLogger(__name__)
-
-def numberToWord(numVal, theLanguage):
- numWord = ""
- if theLanguage == "en":
- numWord = _numberToWordEN(numVal)
- else:
- numWord = _numberToWordEN(numVal)
- # print("%4d : %s" % (numVal, numWord))
- return numWord
-
-def _numberToWordEN(numVal):
-
- numWord = ""
- oneWord = ""
- tenWord = ""
- hunWord = ""
-
- if numVal == 0:
- return "Zero"
-
- oneVal = numVal % 10
- tenVal = (numVal-oneVal) % 100
- hunVal = (numVal-tenVal-oneVal) % 1000
-
- if hunVal == 100: hunWord = "One Hundred"
- if hunVal == 200: hunWord = "Two Hundred"
- if hunVal == 300: hunWord = "Three Hundred"
- if hunVal == 400: hunWord = "Four Hundred"
- if hunVal == 500: hunWord = "Five Hundred"
- if hunVal == 600: hunWord = "Six Hundred"
- if hunVal == 700: hunWord = "Seven Hundred"
- if hunVal == 800: hunWord = "Eight Hundred"
- if hunVal == 900: hunWord = "Nine Hundred"
-
- if tenVal == 20: tenWord = "Twenty"
- if tenVal == 30: tenWord = "Thirty"
- if tenVal == 40: tenWord = "Forty"
- if tenVal == 50: tenWord = "Fifty"
- if tenVal == 60: tenWord = "Sixty"
- if tenVal == 70: tenWord = "Seventy"
- if tenVal == 80: tenWord = "Eighty"
- if tenVal == 90: tenWord = "Ninety"
-
- if tenVal == 10:
- if oneVal == 0: oneWord = "Ten"
- if oneVal == 1: oneWord = "Eleven"
- if oneVal == 2: oneWord = "Twelve"
- if oneVal == 3: oneWord = "Thirteen"
- if oneVal == 4: oneWord = "Fourteen"
- if oneVal == 5: oneWord = "Fifteen"
- if oneVal == 6: oneWord = "Sixteen"
- if oneVal == 7: oneWord = "Seventeen"
- if oneVal == 8: oneWord = "Eighteen"
- if oneVal == 9: oneWord = "Nineteen"
- numWord = ("%s %s" % (hunWord, oneWord)).strip()
- else:
- if oneVal == 0: oneWord = ""
- if oneVal == 1: oneWord = "One"
- if oneVal == 2: oneWord = "Two"
- if oneVal == 3: oneWord = "Three"
- if oneVal == 4: oneWord = "Four"
- if oneVal == 5: oneWord = "Five"
- if oneVal == 6: oneWord = "Six"
- if oneVal == 7: oneWord = "Seven"
- if oneVal == 8: oneWord = "Eight"
- if oneVal == 9: oneWord = "Nine"
- if tenVal == 0:
- numWord = ("%s %s" % (hunWord, oneWord)).strip()
- else:
- if oneVal == 0:
- numWord = ("%s %s" % (hunWord, tenWord)).strip()
- else:
- numWord = ("%s %s-%s" % (hunWord, tenWord, oneWord)).strip()
-
- return numWord
diff --git a/nw/tools/wordcount.py b/nw/tools/wordcount.py
deleted file mode 100644
index 72043158..00000000
--- a/nw/tools/wordcount.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# -*- coding: utf-8 -*-
-"""novelWriter Word Counter
-
- novelWriter – Word Counter
-============================
- Simple word counter
-
- File History:
- Created: 2019-04-22 [0.0.1]
- Moved: 2019-05-30 [0.1.4]
-
- This file is a part of novelWriter
- Copyright 2020, Veronica Berglyd Olsen
-
- This program 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.
-
- This program 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 this program. If not, see .
-"""
-
-import logging
-import nw
-
-logger = logging.getLogger(__name__)
-
-def countWords(theText):
-
- charCount = 0
- wordCount = 0
- paraCount = 0
- prevEmpty = True
-
- for aLine in theText.splitlines():
-
- countPara = True
- theLen = len(aLine)
-
- if theLen == 0:
- prevEmpty = True
- continue
- if aLine[0] == "@" or aLine[0] == "%":
- continue
-
- if aLine[0:5] == "#### ":
- wordCount -= 1
- charCount -= 5
- countPara = False
- elif aLine[0:4] == "### ":
- wordCount -= 1
- charCount -= 4
- countPara = False
- elif aLine[0:3] == "## ":
- wordCount -= 1
- charCount -= 3
- countPara = False
- elif aLine[0:2] == "# ":
- wordCount -= 1
- charCount -= 2
- countPara = False
-
- theBuff = aLine.replace("–"," ").replace("—"," ")
- wordCount += len(theBuff.split())
- charCount += theLen
- if countPara and prevEmpty:
- paraCount += 1
- prevEmpty = countPara == False
-
- return charCount, wordCount, paraCount
From 894bc41f510249c6f94b57d247a31878f81cc143 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 21:32:38 +0200
Subject: [PATCH 7/9] Moved the additions folder into the gui folder as it only
contains gui elements
---
nw/additions/__init__.py | 8 --------
nw/gui/__init__.py | 6 ++++++
nw/gui/additions/__init__.py | 8 ++++++++
nw/{ => gui}/additions/qconfiglayout.py | 0
nw/{ => gui}/additions/qswitch.py | 0
nw/gui/dialogs/configeditor.py | 2 +-
6 files changed, 15 insertions(+), 9 deletions(-)
delete mode 100644 nw/additions/__init__.py
create mode 100644 nw/gui/additions/__init__.py
rename nw/{ => gui}/additions/qconfiglayout.py (100%)
rename nw/{ => gui}/additions/qswitch.py (100%)
diff --git a/nw/additions/__init__.py b/nw/additions/__init__.py
deleted file mode 100644
index 213df1b1..00000000
--- a/nw/additions/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-from nw.additions.qconfiglayout import QConfigLayout
-from nw.additions.qswitch import QSwitch
-
-__all__ = [
- "QConfigLayout",
- "QSwitch",
-]
diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py
index a39d93ad..c59bfed9 100644
--- a/nw/gui/__init__.py
+++ b/nw/gui/__init__.py
@@ -1,5 +1,9 @@
# -*- coding: utf-8 -*-
+# Qt Additions
+from nw.gui.additions.qconfiglayout import QConfigLayout
+from nw.gui.additions.qswitch import QSwitch
+
# Main Window Elements
from nw.gui.icons import GuiIcons
from nw.gui.mainmenu import GuiMainMenu
@@ -33,6 +37,8 @@ from nw.gui.tools.optionstate import OptionState
from nw.gui.tools.wordcounter import WordCounter
__all__ = [
+ "QConfigLayout",
+ "QSwitch",
"GuiIcons",
"GuiMainMenu",
"GuiMainStatus",
diff --git a/nw/gui/additions/__init__.py b/nw/gui/additions/__init__.py
new file mode 100644
index 00000000..04f5e25a
--- /dev/null
+++ b/nw/gui/additions/__init__.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+from nw.gui.additions.qconfiglayout import QConfigLayout
+from nw.gui.additions.qswitch import QSwitch
+
+__all__ = [
+ "QConfigLayout",
+ "QSwitch",
+]
diff --git a/nw/additions/qconfiglayout.py b/nw/gui/additions/qconfiglayout.py
similarity index 100%
rename from nw/additions/qconfiglayout.py
rename to nw/gui/additions/qconfiglayout.py
diff --git a/nw/additions/qswitch.py b/nw/gui/additions/qswitch.py
similarity index 100%
rename from nw/additions/qswitch.py
rename to nw/gui/additions/qswitch.py
diff --git a/nw/gui/dialogs/configeditor.py b/nw/gui/dialogs/configeditor.py
index 7a6f167b..581d7307 100644
--- a/nw/gui/dialogs/configeditor.py
+++ b/nw/gui/dialogs/configeditor.py
@@ -38,7 +38,7 @@ from PyQt5.QtWidgets import (
QFileDialog
)
-from nw.additions import QSwitch, QConfigLayout
+from nw.gui.additions import QSwitch, QConfigLayout
from nw.core import NWSpellCheck, NWSpellSimple, NWSpellEnchant
from nw.constants import nwAlert, nwQuotes
From aea39ba1aadacb402b3c925e30fb3902cf401d11 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 21:33:59 +0200
Subject: [PATCH 8/9] Renamed the textanalyse file
---
lib/{text/analyse.py => textanalyse.py} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename lib/{text/analyse.py => textanalyse.py} (100%)
diff --git a/lib/text/analyse.py b/lib/textanalyse.py
similarity index 100%
rename from lib/text/analyse.py
rename to lib/textanalyse.py
From 76b4ffe0f24afaaea929284a37ddad0087058ada Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 8 May 2020 21:40:56 +0200
Subject: [PATCH 9/9] Add back some file history from deleted files
---
nw/core/tools.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/nw/core/tools.py b/nw/core/tools.py
index f90ae584..2c96cee6 100644
--- a/nw/core/tools.py
+++ b/nw/core/tools.py
@@ -7,8 +7,9 @@
File History:
Created: 2019-04-22 [0.0.1] countWords
- Moved: 2019-05-30 [0.1.4] countWords
+ Created: 2019-10-13 [0.2.3] numberToWord, _numberToWordEN
Created: 2020-02-13 [0.4.3] projectMaintenance
+ Merged: 2020-05-08 [0.4.5] All of the above into this file
This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen