diff --git a/nw/common.py b/nw/common.py
index b148e7df..ada29987 100644
--- a/nw/common.py
+++ b/nw/common.py
@@ -83,8 +83,8 @@ def colRange(rgbStart, rgbEnd, nStep):
return retCol
def splitVersionNumber(vString):
- """ Splits a version string on the form aa.bb.cc into major, minor and patch, and computes an
- integer value aabbcc.
+ """ Splits a version string on the form aa.bb.cc into major, minor
+ and patch, and computes an integer value aabbcc.
"""
vMajor = 0
diff --git a/nw/convert/file/text.py b/nw/convert/file/text.py
index 4d3cd346..0925515b 100644
--- a/nw/convert/file/text.py
+++ b/nw/convert/file/text.py
@@ -100,9 +100,9 @@ class TextFile():
self.fileName = path.basename(filePath)
if path.isfile(filePath) and self.mainConf.showGUI:
msgBox = QMessageBox()
- msgRes = msgBox.question(
- self.theParent, "Overwrite", ("File '%s' already exists.
Do you want to overwrite it?" % self.fileName)
- )
+ msgRes = msgBox.question(self.theParent, "Overwrite", (
+ "File '%s' already exists.
Do you want to overwrite it?" % self.fileName
+ ))
if msgRes != QMessageBox.Yes:
return False
@@ -137,11 +137,14 @@ class TextFile():
return True
def checkInclude(self, tHandle):
- """This function checks whether a file should be included in the export or not. For standard
- note and novel files, this is controlled by the options selected by the user. For other
- files classified as non-exportable, a few checks must be made, and the following are not:
+ """This function checks whether a file should be included in the
+ export or not. For standard note and novel files, this is
+ controlled by the options selected by the user. For other files
+ classified as non-exportable, a few checks must be made, and the
+ following are not:
* Items that are not actual files.
- * Items that have been orphaned which are tagged as NO_LAYOUT and NO_CLASS.
+ * Items that have been orphaned which are tagged as NO_LAYOUT
+ and NO_CLASS.
* Items that appear in the TRASH folder
"""
@@ -168,8 +171,9 @@ class TextFile():
##
def _doOpenFile(self, filePath):
- """This function does the actual opening of the file, and can be overloaded by a subclass
- that uses a different file format that requires a different approach.
+ """This function does the actual opening of the file, and can be
+ overloaded by a subclass that uses a different file format that
+ requires a different approach.
"""
try:
self.outFile = open(filePath,mode="wt+",encoding="utf8")
@@ -180,8 +184,8 @@ class TextFile():
return True
def _doCloseFile(self):
- """This function closes the file, and is meant to be overloaded by the subclass for other
- file formats.
+ """This function closes the file, and is meant to be overloaded
+ by the subclass for other file formats.
"""
if self.outFile is not None:
self.outFile.close()
diff --git a/nw/convert/text/tohtml.py b/nw/convert/text/tohtml.py
index fae40df4..4abdeeb3 100644
--- a/nw/convert/text/tohtml.py
+++ b/nw/convert/text/tohtml.py
@@ -27,8 +27,9 @@ class ToHtml(Tokenizer):
return
def setPreview(self, forPreview, doComments):
- """If we're using this class to generate markdown preview, we need to make a few changes to
- formatting, which is selected by this flag.
+ """If we're using this class to generate markdown preview, we
+ need to make a few changes to formatting, which is selected by
+ this flag.
"""
self.forPreview = forPreview
diff --git a/nw/convert/text/tolatex.py b/nw/convert/text/tolatex.py
index 435fee84..e68cd3b2 100644
--- a/nw/convert/text/tolatex.py
+++ b/nw/convert/text/tolatex.py
@@ -28,7 +28,8 @@ class ToLaTeX(Tokenizer):
return
def doPostProcessing(self):
- """The latexcodec misses dashes and non-breaking spaces, so we do those here.
+ """The latexcodec misses dashes and non-breaking spaces, so we
+ do those here.
"""
repDict = {
@@ -62,8 +63,9 @@ class ToLaTeX(Tokenizer):
begText = "\\begin{center}\n"
endText = "\\end{center}\n\n"
- # First check if we have a comment or plain text, as they need some
- # extra replacing before we proceed to wrapping and final formatting.
+ # First check if we have a comment or plain text, as they
+ # need some extra replacing before we proceed to wrapping
+ # and final formatting.
if tType == self.T_COMMENT:
tText = "%% %s" % tText
@@ -75,8 +77,9 @@ class ToLaTeX(Tokenizer):
tLen = len(tText)
- # Then the text can receive final formatting before we append it to the results.
- # We also store text lines in a buffer and merge them only when we find an empty line
+ # Then the text can receive final formatting before we
+ # append it to the results. We also store text lines in a
+ # buffer and merge them only when we find an empty line
# indicating a new paragraph.
if tType == self.T_EMPTY:
if len(thisPar) > 0:
diff --git a/nw/convert/text/tomarkdown.py b/nw/convert/text/tomarkdown.py
index 78098c5e..c9ea57b7 100644
--- a/nw/convert/text/tomarkdown.py
+++ b/nw/convert/text/tomarkdown.py
@@ -55,8 +55,9 @@ class ToMarkdown(Tokenizer):
thisPar = []
for tType, tText, tFormat, tAlign in self.theTokens:
- # First check if we have a comment or plain text, as they need some
- # extra replacing before we proceed to wrapping and final formatting.
+ # First check if we have a comment or plain text, as they
+ # need some extra replacing before we proceed to wrapping
+ # and final formatting.
if tType == self.T_COMMENT:
tText = " %s" % tText
@@ -68,7 +69,8 @@ class ToMarkdown(Tokenizer):
tLen = len(tText)
- # The text can now be word wrapped, if we have requested this and it's needed.
+ # The text can now be word wrapped, if we have requested
+ # this and it's needed.
if self.wordWrap > 0 and tLen > self.wordWrap:
if tType == self.T_COMMENT:
tText = textwrap.fill(
@@ -77,8 +79,9 @@ class ToMarkdown(Tokenizer):
else:
tText = tWrap.fill(tText)
- # Then the text can receive final formatting before we append it to the results.
- # We also store text lines in a buffer and merge them only when we find an empty line,
+ # Then the text can receive final formatting before we
+ # append it to the results. We also store text lines in a
+ # buffer and merge them only when we find an empty line,
# indicating a new paragraph.
if tType == self.T_EMPTY:
if len(thisPar) > 0:
diff --git a/nw/convert/text/totext.py b/nw/convert/text/totext.py
index e6073012..e7fdb9d2 100644
--- a/nw/convert/text/totext.py
+++ b/nw/convert/text/totext.py
@@ -61,8 +61,9 @@ class ToText(Tokenizer):
thisPar = []
for tType, tText, tFormat, tAlign in self.theTokens:
- # First check if we have a comment or plain text, as they need some
- # extra replacing before we proceed to wrapping and final formatting.
+ # First check if we have a comment or plain text, as they
+ # need some extra replacing before we proceed to wrapping
+ # and final formatting.
if tType == self.T_COMMENT:
tText = "[%s]" % tText
@@ -74,7 +75,8 @@ class ToText(Tokenizer):
tLen = len(tText)
- # The text can now be word wrapped, if we have requested this and it's needed.
+ # The text can now be word wrapped, if we have requested
+ # this and it's needed.
if tAlign == self.A_CENTRE:
if self.wordWrap > 0:
if tLen > self.wordWrap:
@@ -88,8 +90,9 @@ class ToText(Tokenizer):
if self.wordWrap > 0 and tLen > self.wordWrap:
tText = tWrap.fill(tText)
- # Then the text can receive final formatting before we append it to the results.
- # We also store text lines in a buffer and merge them only when we find an empty line,
+ # Then the text can receive final formatting before we
+ # append it to the results. We also store text lines in a
+ # buffer and merge them only when we find an empty line,
# indicating a new paragraph.
if tType == self.T_EMPTY:
if len(thisPar) > 0:
diff --git a/nw/convert/tokenizer.py b/nw/convert/tokenizer.py
index acc90b91..e391aab7 100644
--- a/nw/convert/tokenizer.py
+++ b/nw/convert/tokenizer.py
@@ -153,10 +153,11 @@ class Tokenizer():
return
def tokenizeText(self):
- """Scan the text for either lines starting with specific characters that indicate headers,
- comments, commands etc, or just contains plain text. in the case of plain text, apply the
- same RegExes that the syntax highlighter uses and save the locations of these formatting
- tags into the token array.
+ """Scan the text for either lines starting with specific
+ characters that indicate headers, comments, commands etc, or
+ just contains plain text. in the case of plain text, apply the
+ same RegExes that the syntax highlighter uses and save the
+ locations of these formatting tags into the token array.
"""
# RegExes for adding formatting tags within text lines
diff --git a/nw/gui/dialogs/export.py b/nw/gui/dialogs/export.py
index d3be1260..ea2eb0bf 100644
--- a/nw/gui/dialogs/export.py
+++ b/nw/gui/dialogs/export.py
@@ -362,8 +362,8 @@ class GuiExportMain(QWidget):
"Comments are exported as LaTeX comments."
),
FMT_PDOC : (
- "Exports first to markdown or html5. The file is then passed on to Pandoc for a second "
- "stage. Use the Pandoc tab for settings up the conversion."
+ "Exports first to markdown or html5. The file is then passed on to Pandoc for a "
+ "second stage. Use the Pandoc tab for settings up the conversion."
),
}
@@ -537,7 +537,8 @@ class GuiExportMain(QWidget):
##
def _updateFormat(self, currIdx):
- """Update help text under output format selection and file extension in file box
+ """Update help text under output format selection and file
+ extension in file box
"""
if currIdx == -1:
self.outputHelp.setText("")
diff --git a/nw/gui/dialogs/sessionlog.py b/nw/gui/dialogs/sessionlog.py
index be2a1f94..0afd21c5 100644
--- a/nw/gui/dialogs/sessionlog.py
+++ b/nw/gui/dialogs/sessionlog.py
@@ -51,9 +51,15 @@ class GuiSessionLogView(QDialog):
self.setMinimumWidth(420)
self.setMinimumHeight(400)
- widthCol0 = self.optState.validIntRange(self.optState.getSetting("widthCol0"), 30, 999, 180)
- widthCol1 = self.optState.validIntRange(self.optState.getSetting("widthCol1"), 30, 999, 80)
- widthCol2 = self.optState.validIntRange(self.optState.getSetting("widthCol2"), 30, 999, 80)
+ widthCol0 = self.optState.validIntRange(
+ self.optState.getSetting("widthCol0"), 30, 999, 180
+ )
+ widthCol1 = self.optState.validIntRange(
+ self.optState.getSetting("widthCol1"), 30, 999, 80
+ )
+ widthCol2 = self.optState.validIntRange(
+ self.optState.getSetting("widthCol2"), 30, 999, 80
+ )
self.listBox = QTreeWidget()
self.listBox.setHeaderLabels(["Session Start","Length","Words",""])
diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py
index e2214b03..4a21ddac 100644
--- a/nw/gui/elements/doceditor.py
+++ b/nw/gui/elements/doceditor.py
@@ -136,9 +136,9 @@ class GuiDocEditor(QTextEdit):
return True
def initEditor(self):
- """Initialise or re-initialise the editor with the user's settings.
- This function is both called when the editor is created, and when the user changes the
- main editor preferences.
+ """Initialise or re-initialise the editor with the user's
+ settings. This function is both called when the editor is
+ created, and when the user changes the main editor preferences.
"""
# Reload dictionaries
@@ -179,10 +179,12 @@ class GuiDocEditor(QTextEdit):
# Initialise the syntax highlighter
self.hLight.initHighlighter()
- # If we have a document open, we should reload it in case the font changed, otherwise
- # we just clear the editor entirely, which makes it read only.
+ # If we have a document open, we should reload it in case the
+ # font changed, otherwise we just clear the editor entirely,
+ # which makes it read only.
if self.theHandle is not None:
- # We must save the current handle as clearEditor() sets it to None
+ # We must save the current handle as clearEditor() sets it
+ # to None
tHandle = self.theHandle
self.clearEditor()
self.loadText(tHandle)
@@ -193,11 +195,13 @@ class GuiDocEditor(QTextEdit):
return True
def loadText(self, tHandle):
- """Load text from a document into the editor. If we have an io error, we must handle this
- and clear the editor so that we don't risk overwriting the file if it exists. This can for
- instance happen of the file contains binary elements or an encoding that novelWriter does
- not support. If load is successful, ot the document is new (empty string) we set up the
- editor for editing the file.
+ """Load text from a document into the editor. If we have an io
+ error, we must handle this and clear the editor so that we don't
+ risk overwriting the file if it exists. This can for instance
+ happen of the file contains binary elements or an encoding that
+ novelWriter does not support. If load is successful, or the
+ document is new (empty string) we set up the editor for editing
+ the file.
"""
theDoc = self.nwDocument.openDocument(tHandle)
@@ -251,8 +255,9 @@ class GuiDocEditor(QTextEdit):
return self.docChanged
def getText(self):
- """Get the text content of the current document. This method uses QTextEdit->toPlainText for
- Qt versions lower than 5.9, and the QDocument->toRawText for higher version. The latter
+ """Get the text content of the current document. This method
+ uses QTextEdit->toPlainText for Qt versions lower than 5.9, and
+ the QDocument->toRawText for higher version. The latter
preserves non-breaking spaces, which the former does not.
"""
if self.mainConf.verQtValue >= 50900:
@@ -296,8 +301,8 @@ class GuiDocEditor(QTextEdit):
##
def changeWidth(self):
- """Automatically adjust the margins so the text is centred, but only if Config.textFixedW is
- set to True.
+ """Automatically adjust the margins so the text is centred, but
+ only if Config.textFixedW is set to True.
"""
if self.mainConf.textFixedW:
vBar = self.verticalScrollBar()
@@ -322,23 +327,40 @@ class GuiDocEditor(QTextEdit):
if not self.theParent.hasProject:
logger.error("No project open")
return False
- if theAction == nwDocAction.UNDO: self.undo()
- elif theAction == nwDocAction.REDO: self.redo()
- elif theAction == nwDocAction.CUT: self.cut()
- elif theAction == nwDocAction.COPY: self.copy()
- elif theAction == nwDocAction.PASTE: self.paste()
- elif theAction == nwDocAction.BOLD: self._wrapSelection("**","**")
- elif theAction == nwDocAction.ITALIC: self._wrapSelection("_","_")
- elif theAction == nwDocAction.U_LINE: self._wrapSelection("__","__")
- elif theAction == nwDocAction.S_QUOTE: self._wrapSelection(self.typSQOpen,self.typSQClose)
- elif theAction == nwDocAction.D_QUOTE: self._wrapSelection(self.typDQOpen,self.typDQClose)
- elif theAction == nwDocAction.SEL_ALL: self._makeSelection(QTextCursor.Document)
- elif theAction == nwDocAction.SEL_PARA: self._makeSelection(QTextCursor.BlockUnderCursor)
- elif theAction == nwDocAction.FIND: self._beginSearch()
- elif theAction == nwDocAction.REPLACE: self._beginReplace()
- elif theAction == nwDocAction.GO_NEXT: self._findNext()
- elif theAction == nwDocAction.GO_PREV: self._findPrev()
- elif theAction == nwDocAction.REPL_NEXT: self._replaceNext()
+ if theAction == nwDocAction.UNDO:
+ self.undo()
+ elif theAction == nwDocAction.REDO:
+ self.redo()
+ elif theAction == nwDocAction.CUT:
+ self.cut()
+ elif theAction == nwDocAction.COPY:
+ self.copy()
+ elif theAction == nwDocAction.PASTE:
+ self.paste()
+ elif theAction == nwDocAction.BOLD:
+ self._wrapSelection("**","**")
+ elif theAction == nwDocAction.ITALIC:
+ self._wrapSelection("_","_")
+ elif theAction == nwDocAction.U_LINE:
+ self._wrapSelection("__","__")
+ elif theAction == nwDocAction.S_QUOTE:
+ self._wrapSelection(self.typSQOpen,self.typSQClose)
+ elif theAction == nwDocAction.D_QUOTE:
+ self._wrapSelection(self.typDQOpen,self.typDQClose)
+ elif theAction == nwDocAction.SEL_ALL:
+ self._makeSelection(QTextCursor.Document)
+ elif theAction == nwDocAction.SEL_PARA:
+ self._makeSelection(QTextCursor.BlockUnderCursor)
+ elif theAction == nwDocAction.FIND:
+ self._beginSearch()
+ elif theAction == nwDocAction.REPLACE:
+ self._beginReplace()
+ elif theAction == nwDocAction.GO_NEXT:
+ self._findNext()
+ elif theAction == nwDocAction.GO_PREV:
+ self._findPrev()
+ elif theAction == nwDocAction.REPL_NEXT:
+ self._replaceNext()
else:
logger.error("Unknown or unsupported document action %s" % str(theAction))
return False
@@ -366,13 +388,15 @@ class GuiDocEditor(QTextEdit):
def keyPressEvent(self, keyEvent):
"""Intercept key press events.
- We need to intercept key presses briefly to record the state of selection. This is in order
- to know whether we had a selection prior to triggering the _docChange slot, as we do not
- want to trigger autoreplace on selections. Autoreplace on selections messes with undo/redo
- history.
- We also need to intercept the Shift key modifier for certain key combinations that modifies
- standard keys like enter and space. However, we don't want to spend a lot of time in this
- function as it is triggered on every keypress when typing.
+ We need to intercept key presses briefly to record the state of
+ selection. This is in order to know whether we had a selection
+ prior to triggering the _docChange slot, as we do not want to
+ trigger autoreplace on selections. Autoreplace on selections
+ messes with undo/redo history.
+ We also need to intercept the Shift key modifier for certain key
+ combinations that modifies standard keys like enter and space.
+ However, we don't want to spend a lot of time in this function
+ as it is triggered on every keypress when typing.
"""
self.hasSelection = self.textCursor().hasSelection()
@@ -393,8 +417,9 @@ class GuiDocEditor(QTextEdit):
return
def mouseReleaseEvent(self, mEvent):
- """If the mouse button is released and the control key is pressed, check if we're clicking
- on a tag, and trigger the follow tag function.
+ """If the mouse button is released and the control key is
+ pressed, check if we're clicking on a tag, and trigger the
+ follow tag function.
"""
if qApp.keyboardModifiers() == Qt.ControlModifier:
theCursor = self.cursorForPosition(mEvent.pos())
@@ -407,9 +432,11 @@ class GuiDocEditor(QTextEdit):
##
def _followTag(self, theCursor=None):
- """Activated by Ctrl+Enter. Checks that we're in a block starting with '@'. We then find the
- word under the cursor and check that it is after the ':'. If all this is fine, we have a tag
- and can tell the document viewer to try and find and load the file where the tag is defined.
+ """Activated by Ctrl+Enter. Checks that we're in a block
+ starting with '@'. We then find the word under the cursor and
+ check that it is after the ':'. If all this is fine, we have a
+ tag and can tell the document viewer to try and find and load
+ the file where the tag is defined.
"""
if theCursor is None:
@@ -574,7 +601,8 @@ class GuiDocEditor(QTextEdit):
return
def _runCounter(self):
- """Decide whether to run the word counter, or stop the timer due to inactivity.
+ """Decide whether to run the word counter, or stop the timer due
+ to inactivity.
"""
sinceActive = time()-self.lastEdit
if sinceActive > 5*self.wcInterval:
@@ -603,9 +631,10 @@ class GuiDocEditor(QTextEdit):
return
def _wrapSelection(self, tBefore, tAfter):
- """Wraps the selected text in whatever is in tBefore and tAfter. If there is no selection,
- the autoSelect setting decides the action. AutoSelect will select the word under the cursor
- before wrapping it. If this feature is disabled, nothing is done.
+ """Wraps the selected text in whatever is in tBefore and tAfter.
+ If there is no selection, the autoSelect setting decides the
+ action. AutoSelect will select the word under the cursor before
+ wrapping it. If this feature is disabled, nothing is done.
"""
theCursor = self.textCursor()
if self.mainConf.autoSelect and not theCursor.hasSelection():
@@ -643,15 +672,16 @@ class GuiDocEditor(QTextEdit):
return
def _beginReplace(self):
- """Opens the replace line of the search bar and sets the replace text.
+ """Opens the replace line of the search bar and sets the replace
+ text.
"""
self._beginSearch()
self.theParent.searchBar.setReplaceText("")
return
def _findNext(self):
- """Searches for the next occurrence of the search bar text in the document.
- Wraps back to the top if not found.
+ """Searches for the next occurrence of the search bar text in
+ the document. Wraps back to the top if not found.
"""
searchFor = self.theParent.searchBar.getSearchText()
wasFound = self.find(searchFor)
@@ -662,8 +692,8 @@ class GuiDocEditor(QTextEdit):
return
def _findPrev(self):
- """Searches for the previous occurrence of the search bar text in the document.
- Wraps back to the end if not found.
+ """Searches for the previous occurrence of the search bar text
+ in the document. Wraps back to the end if not found.
"""
searchFor = self.theParent.searchBar.getSearchText()
wasFound = self.find(searchFor, QTextDocument.FindBackward)
@@ -674,8 +704,9 @@ class GuiDocEditor(QTextEdit):
return
def _replaceNext(self):
- """Searches for the next occurrence of the search bar text in the document and replaces it
- with the replace text. Wraps back to the top if not found.
+ """Searches for the next occurrence of the search bar text in
+ the document and replaces it with the replace text. Wraps back
+ to the top if not found.
"""
theCursor = self.textCursor()
searchFor = self.theParent.searchBar.getSearchText()
diff --git a/nw/gui/elements/doctree.py b/nw/gui/elements/doctree.py
index 854ceac4..bafa5b48 100644
--- a/nw/gui/elements/doctree.py
+++ b/nw/gui/elements/doctree.py
@@ -129,7 +129,8 @@ class GuiDocTree(QTreeWidget):
tHandle = self.theProject.newRoot(nwLabels.CLASS_NAME[itemClass], itemClass)
else:
- # If no parent has been selected, make the new file under the root NOVEL item.
+ # If no parent has been selected, make the new file under
+ # the root NOVEL item.
if pHandle is None:
pHandle = self.theProject.findRootItem(nwItemClass.NOVEL)
@@ -138,7 +139,8 @@ class GuiDocTree(QTreeWidget):
logger.error("Did not find anywhere to add the item!")
return False
- # Now check if the selected item is a file, in which case the new file will be a sibling
+ # Now check if the selected item is a file, in which case
+ # the new file will be a sibling
pItem = self.theProject.getItem(pHandle)
if pItem.itemType == nwItemType.FILE:
pHandle = pItem.parHandle
@@ -177,8 +179,8 @@ class GuiDocTree(QTreeWidget):
return True
def moveTreeItem(self, nStep):
- """Move an item up or down in the tree, but only if the treeView has focus. This also
- applies when the menu is used.
+ """Move an item up or down in the tree, but only if the treeView
+ has focus. This also applies when the menu is used.
"""
if QApplication.focusWidget() == self and self.theParent.hasProject:
tHandle = self.getSelectedHandle()
@@ -225,10 +227,11 @@ class GuiDocTree(QTreeWidget):
return retVals
def deleteItem(self, tHandle=None):
- """Delete items from the tree. Note that this does not delete the item from the item tree in
- the project object. However, since this is only meta data, there isn't really a need to do
- that to save memory. Items not in the tree are not saved to the project file, so a loaded
- project will be clean anyway.
+ """Delete items from the tree. Note that this does not delete
+ the item from the item tree in the project object. However,
+ since this is only meta data, there isn't really a need to do
+ that to save memory. Items not in the tree are not saved to the
+ project file, so a loaded project will be clean anyway.
"""
if tHandle is None:
@@ -453,8 +456,9 @@ class GuiDocTree(QTreeWidget):
return
def _updateItemParent(self, tHandle):
- """Update the parent handle of an item so that the information in the project is consistent
- with the treeView. Also move the word count over to the new parent tree.
+ """Update the parent handle of an item so that the information
+ in the project is consistent with the treeView. Also move the
+ word count over to the new parent tree.
"""
trItemS = self._getTreeItem(tHandle)
@@ -496,8 +500,8 @@ class GuiDocTree(QTreeWidget):
##
def mousePressEvent(self, theEvent):
- """Overload mousePressEvent to clear selection if clicking the mouse in a blank
- area of the tree view.
+ """Overload mousePressEvent to clear selection if clicking the
+ mouse in a blank area of the tree view.
"""
QTreeWidget.mousePressEvent(self, theEvent)
selItem = self.indexAt(theEvent.pos())
@@ -506,8 +510,8 @@ class GuiDocTree(QTreeWidget):
return
def dropEvent(self, theEvent):
- """Overload the drop of dragged item event to check whether the drop is allowed
- or not. Disallowed drops are cancelled.
+ """Overload the drop of dragged item event to check whether the
+ drop is allowed or not. Disallowed drops are cancelled.
"""
sHandle = self.getSelectedHandle()
if sHandle is None:
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index 49551b9b..ffa876c5 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -17,7 +17,7 @@ from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QIcon, QDesktopServices
from PyQt5.QtWidgets import QMenuBar, QAction, QMessageBox
-from nw.enum import nwItemType, nwItemClass, nwDocAction
+from nw.enum import nwItemType, nwItemClass, nwDocAction
logger = logging.getLogger(__name__)
@@ -122,8 +122,9 @@ class GuiMainMenu(QMenuBar):
aboutMsg = (
"
Version: {version:s}
Release Date: {date:s}
{name:s} is a markdown-like text editor designed for organising and writing novels. " - "It is written in Python 3 with a Qt5 GUI, using PyQt5
" + "{name:s} is a markdown-like text editor designed for organising " + "and writing novels. It is written in Python 3 with a Qt5 GUI, " + "using PyQt5
" "{name:s} is licensed under GPL v3.0
" "{copyright:s}
" "Website: {website:s}
" diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py index a6bf6f01..8eedb626 100644 --- a/nw/gui/winmain.py +++ b/nw/gui/winmain.py @@ -244,7 +244,8 @@ class GuiMain(QMainWindow): def closeProject(self, isYes=False): """Closes the project if one is open. - isYes is passed on from the close application event so the user doesn't get prompted twice. + isYes is passed on from the close application event so the user + doesn't get prompted twice. """ if not self.hasProject: # There is no project loaded, everything OK @@ -288,15 +289,17 @@ class GuiMain(QMainWindow): return saveOK def openProject(self, projFile=None): - """Open a project. The parameter projFile is passed from the open recent projects menu, so - can be set. If not, we pop the dialog. + """Open a project. The parameter projFile is passed from the + open recent projects menu, so can be set. If not, we pop the + dialog. """ if projFile is None: projFile = self.openProjectDialog() if projFile is None: return False - # Make sure any open project is cleared out first before we load another one + # Make sure any open project is cleared out first before we load + # another one if not self.closeProject(): return False @@ -629,8 +632,9 @@ class GuiMain(QMainWindow): return True def makeAlert(self, theMessage, theLevel=nwAlert.INFO): - """Alert both the user and the logger at the same time. Message can be either a string or an - array of strings. Severity level is 0 = info, 1 = warning, and 2 = error. + """Alert both the user and the logger at the same time. Message + can be either a string or an array of strings. Severity level is + 0 = info, 1 = warning, and 2 = error. """ if isinstance(theMessage, list): @@ -724,7 +728,8 @@ class GuiMain(QMainWindow): return True def _autoSaveProject(self): - if self.hasProject and self.theProject.projChanged and self.theProject.projPath is not None: + if (self.hasProject and self.theProject.projChanged and + self.theProject.projPath is not None): logger.debug("Autosaving project") self.saveProject(isAuto=True) return @@ -756,8 +761,8 @@ class GuiMain(QMainWindow): ## def resizeEvent(self, theEvent): - """Extend QMainWindow.resizeEvent to signal dependent GUI elements that its pane may have - changed size. + """Extend QMainWindow.resizeEvent to signal dependent GUI + elements that its pane may have changed size. """ QMainWindow.resizeEvent(self,theEvent) self.docEditor.changeWidth() @@ -803,7 +808,8 @@ class GuiMain(QMainWindow): return def _keyPressEscape(self): - """When the escape key is pressed somewhere in the main window, do the following, in order. + """When the escape key is pressed somewhere in the main window, + do the following, in order. """ if self.searchBar.isVisible(): self.searchBar.setVisible(False) @@ -811,13 +817,15 @@ class GuiMain(QMainWindow): return def _splitMainMove(self, pWidth, pHeight): - """Alert dependent GUI elements that the main pane splitter has been moved. + """Alert dependent GUI elements that the main pane splitter has + been moved. """ self.docEditor.changeWidth() return def _splitViewMove(self, pWidth, pHeight): - """Alert dependent GUI elements that the main pane splitter has been moved. + """Alert dependent GUI elements that the main pane splitter has + been moved. """ self.docEditor.changeWidth() return diff --git a/nw/project/document.py b/nw/project/document.py index e54a72f0..3e807a2b 100644 --- a/nw/project/document.py +++ b/nw/project/document.py @@ -53,7 +53,8 @@ class NWDoc(): self.clearDocument() return None - # By default, the document is editable. Except for files in the trash folder. + # By default, the document is editable. + # Except for files in the trash folder. self.docEditable = True if self.theItem.parHandle == self.theProject.trashRoot: self.docEditable = False @@ -70,13 +71,14 @@ class NWDoc(): theDoc = inFile.read() except Exception as e: self.makeAlert(["Failed to open document file.",str(e)], nwAlert.ERROR) - # Note: Document must be cleared in case of an io error, or else the auto-save or - # save will try to overwrite it with an empty file. Return None to alert the caller. + # Note: Document must be cleared in case of an io error, + # or else the auto-save or save will try to overwrite it + # with an empty file. Return None to alert the caller. self.clearDocument() return None else: - # The document file does not exist, so we assume it's a new document and initialise an - # empty text string. + # The document file does not exist, so we assume it's a new + # document and initialise an empty text string. logger.debug("The requested document does not exist.") return "" diff --git a/nw/project/index.py b/nw/project/index.py index db7d21e1..d3b62613 100644 --- a/nw/project/index.py +++ b/nw/project/index.py @@ -130,7 +130,8 @@ class NWIndex(): return False def saveIndex(self): - """Save the current index as a json file in the project meta folder. + """Save the current index as a json file in the project meta + folder. """ indexFile = path.join(self.theProject.projMeta, nwFiles.INDEX_FILE) @@ -155,7 +156,8 @@ class NWIndex(): return True def checkIndex(self): - """Check that the entries in the index are valid and contain the elements it should. + """Check that the entries in the index are valid and contain the + elements it should. """ self.indexBroken = False @@ -193,8 +195,9 @@ class NWIndex(): ## def scanText(self, tHandle, theText): - """Scan a piece of text associated with a handle. This will update the indices accordingly. - This function takes the handle and text as separate inputs as we want to primarily scan the + """Scan a piece of text associated with a handle. This will + update the indices accordingly. This function takes the handle + and text as separate inputs as we want to primarily scan the files before we save them, unless we're rebuilding the index. """ @@ -243,7 +246,8 @@ class NWIndex(): return True def indexTitle(self, tHandle, isNovel, aLine, nLine, itemLayout): - """Save information about the title and its location in the file. + """Save information about the title and its location in the + file. """ if aLine.startswith("# "): @@ -272,7 +276,8 @@ class NWIndex(): return True def indexNoteRef(self, tHandle, aLine, nLine, nTitle): - """Validate and save the information about a reference to a tag in another file. + """Validate and save the information about a reference to a tag + in another file. """ isValid, theBits, thePos = self.scanThis(aLine) @@ -303,8 +308,9 @@ class NWIndex(): ## def scanThis(self, aLine): - """Scan a line starting with @ to check that it's valid and to split up its elements into - an array and an array of positions. The latter is needed for the syntax highlighter. + """Scan a line starting with @ to check that it's valid and to + split up its elements into an array and an array of positions. + The latter is needed for the syntax highlighter. """ theBits = [] @@ -343,8 +349,8 @@ class NWIndex(): return True, theBits, thePos def checkThese(self, theBits, tItem): - """Check the tags against the index to see if they are valid tags. This is needed for syntax - highlighting. + """Check the tags against the index to see if they are valid + tags. This is needed for syntax highlighting. """ nBits = len(theBits) @@ -357,7 +363,8 @@ class NWIndex(): if not isGood[0] or nBits == 1: return isGood - # If we have a tag, only the first value is accepted, the rest is ignored + # If we have a tag, only the first value is accepted, the rest + # is ignored if theBits[0] == nwKeyWords.TAG_KEY and nBits > 1: isGood[0] = True if theBits[1] in self.tagIndex.keys(): @@ -396,7 +403,8 @@ class NWIndex(): return True def buildReferenceList(self, tHandle): - """Build a list of files referring back to our file, specified by tHandle. + """Build a list of files referring back to our file, specified + by tHandle. """ theRefs = {} @@ -429,8 +437,9 @@ class NWIndex(): return None, 0 def buildTagNovelMap(self, theTags, theFilters=None): - """Build a two-dimensional map of all titles of the novel and which tags they link to from - the various meta tags. This map is used to display the timeline view. + """Build a two-dimensional map of all titles of the novel and + which tags they link to from the various meta tags. This map is + used to display the timeline view. """ tagMap = {} diff --git a/nw/project/item.py b/nw/project/item.py index 55d532a1..9640265b 100644 --- a/nw/project/item.py +++ b/nw/project/item.py @@ -85,17 +85,28 @@ class NWItem(): def setFromTag(self, tagName, tagValue): logger.verbose("Setting tag '%s' to value '%s'" % (tagName, str(tagValue))) - if tagName == "name": self.setName(tagValue) - elif tagName == "order": self.setOrder(tagValue) - elif tagName == "type": self.setType(tagValue) - elif tagName == "class": self.setClass(tagValue) - elif tagName == "layout": self.setLayout(tagValue) - elif tagName == "status": self.setStatus(tagValue) - elif tagName == "expanded": self.setExpanded(tagValue) - elif tagName == "charCount": self.setCharCount(tagValue) - elif tagName == "wordCount": self.setWordCount(tagValue) - elif tagName == "paraCount": self.setParaCount(tagValue) - elif tagName == "cursorPos": self.setCursorPos(tagValue) + if tagName == "name": + self.setName(tagValue) + elif tagName == "order": + self.setOrder(tagValue) + elif tagName == "type": + self.setType(tagValue) + elif tagName == "class": + self.setClass(tagValue) + elif tagName == "layout": + self.setLayout(tagValue) + elif tagName == "status": + self.setStatus(tagValue) + elif tagName == "expanded": + self.setExpanded(tagValue) + elif tagName == "charCount": + self.setCharCount(tagValue) + elif tagName == "wordCount": + self.setWordCount(tagValue) + elif tagName == "paraCount": + self.setParaCount(tagValue) + elif tagName == "cursorPos": + self.setCursorPos(tagValue) else: logger.error("Unknown tag '%s'" % tagName) return diff --git a/nw/project/project.py b/nw/project/project.py index 9a0bfd03..a0208885 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -37,7 +37,7 @@ class NWProject(): self.mainConf = self.theParent.mainConf self.projOpened = None # The time stamp of when the project file was opened self.projChanged = None # The project has unsaved changes - self.projAltered = None # The project has been altered this session (used to trigger backup) + self.projAltered = None # The project has been altered this session # Debug self.handleSeed = None @@ -224,7 +224,8 @@ class NWProject(): if xChild.tag == "project": logger.debug("Found project meta") for xItem in xChild: - if xItem.text is None: continue + if xItem.text is None: + continue if xItem.tag == "name": logger.verbose("Working Title: '%s'" % xItem.text) self.projName = xItem.text @@ -239,7 +240,8 @@ class NWProject(): elif xChild.tag == "settings": logger.debug("Found project settings") for xItem in xChild: - if xItem.text is None: continue + if xItem.text is None: + continue if xItem.tag == "spellCheck": self.spellCheck = checkBool(xItem.text,False) elif xItem.tag == "lastEdited": @@ -493,8 +495,9 @@ class NWProject(): return None def getRootItem(self, tHandle): - """Iterate upwards in the tree until we find the item with parent None, the root item. - We do this with a for loop with a maximum depth of 200 to make infinite loops impossible. + """Iterate upwards in the tree until we find the item with + parent None, the root item. We do this with a for loop with a + maximum depth of 200 to make infinite loops impossible. """ tItem = self.getItem(tHandle) if tItem is not None: @@ -506,9 +509,10 @@ class NWProject(): return None def getProjectItems(self): - """This function is called from the tree view when building the tree. Each item in the - project is returned in the order saved in the project file, but first it checks that it has - a parent item already sent to the tree. + """This function is called from the tree view when building the + tree. Each item in the project is returned in the order saved in + the project file, but first it checks that it has a parent item + already sent to the tree. """ sentItems = [] iterItems = self.treeOrder.copy() @@ -521,10 +525,12 @@ class NWProject(): if n > 10000: return # Just in case if tItem is None: - # Technically a bug since treeOrder is built from the same data as projTree + # Technically a bug since treeOrder is built from the + # same data as projTree continue elif tItem.parHandle is None: - # Item is a root, or already been identified as an orphaned item + # Item is a root, or already been identified as an + # orphaned item sentItems.append(tHandle) yield tItem elif tItem.parHandle in sentItems: @@ -532,7 +538,8 @@ class NWProject(): sentItems.append(tHandle) yield tItem elif tItem.parHandle in iterItems: - # Item's parent exists, but hasn't been sent yet, so add it again to the end + # Item's parent exists, but hasn't been sent yet, so add + # it again to the end logger.warning("Item %s found before its parent" % tHandle) iterItems.append(tHandle) nMax = len(iterItems) @@ -547,7 +554,8 @@ class NWProject(): ## def deleteItem(self, tHandle): - """This only removes the item from the order list, but not from the project tree. + """This only removes the item from the order list, but not from + the project tree. """ self.treeOrder.remove(tHandle) self.setProjectChanged(True) @@ -560,8 +568,8 @@ class NWProject(): return None def checkRootUnique(self, theClass): - """Checks if there already is a root entry of class 'theClass' in the - root of the project tree. + """Checks if there already is a root entry of class 'theClass' + in the root of the project tree. """ if theClass == nwItemClass.CUSTOM: return True @@ -689,7 +697,9 @@ class NWProject(): if self.projMeta is None: return False - with open(path.join(self.projMeta, nwFiles.SESS_INFO),mode="a+",encoding="utf8") as outFile: + sessionFile = path.join(self.projMeta, nwFiles.SESS_INFO) + + with open(sessionFile,mode="a+",encoding="utf8") as outFile: print(( "Start: {opened:s} " "End: {closed:s} " @@ -717,9 +727,10 @@ class NWProject(): return itemHandle def _maintainPrevious(self): - """This function will take the current project file and copy it into the project cache - folder with an incremental file extension added. These serve as a backup in case the xml - file gets corrupted. + """This function will take the current project file and copy it + into the project cache folder with an incremental file extension + added. These serve as a backup in case the xml file gets + corrupted. """ countFile = path.join(self.projCache, nwFiles.PROJ_COUNT) diff --git a/nw/project/status.py b/nw/project/status.py index ea1a045a..d3bbb560 100644 --- a/nw/project/status.py +++ b/nw/project/status.py @@ -13,7 +13,7 @@ import logging import nw -from lxml import etree +from lxml import etree from nw.enum import nwItemClass from nw.common import checkInt diff --git a/nw/tools/analyse.py b/nw/tools/analyse.py index 37076063..bb847d74 100644 --- a/nw/tools/analyse.py +++ b/nw/tools/analyse.py @@ -58,7 +58,7 @@ class TextAnalysis(): return rScore, gLevel def getReadabilityText(self, rScore): - if rScore >= 90.0: + if rScore >= 90.0: return "Very Easy" elif rScore >= 80.0: return "Easy" @@ -78,13 +78,15 @@ class TextAnalysis(): # def _countWords(self): - """Counts the number of words in a text by simply splitting on all white spaces. + """Counts the number of words in a text by simply splitting on + all white spaces. """ return len(self.theText.strip().split()) def _countSentences(self): - """Counts the number of non-repeated sentence endings seen in the text. - Note: This will count filenames and urls as multiple sentences. + """Counts the number of non-repeated sentence endings seen in + the text. Note: This will count filenames and urls as multiple + sentences. """ nSent = 0 sawEnd = False @@ -98,7 +100,8 @@ class TextAnalysis(): return nSent def _countParagraphs(self, pThreshold=2): - """Counts the number of paragraphs by counting repeated line breaks. + """Counts the number of paragraphs by counting repeated line + breaks. """ nPara = 1 sawEnd = 0 @@ -114,9 +117,10 @@ class TextAnalysis(): return nPara def _countSyllablesEN(self): - """Attempt to count the syllables in a piece of English language text. - This function tends to slightly over-estimate the number of syllables as it doesn't handle - the complexity of silent vowels in endings very well. It will count them all. + """Attempt to count the syllables in a piece of English language + text. This function tends to slightly over-estimate the number + of syllables as it doesn't handle the complexity of silent + vowels in endings very well. It will count them all. """ cleanText = "" @@ -160,7 +164,6 @@ class TextAnalysis(): nSyll += 1 if nSyll < 1: nSyll = 1 - # print("%-15s: %d" % (inWord,nSyll)) allSylls += nSyll return allSylls/len(theWords) diff --git a/nw/tools/spellenchant.py b/nw/tools/spellenchant.py index b2faa472..cf4f1574 100644 --- a/nw/tools/spellenchant.py +++ b/nw/tools/spellenchant.py @@ -32,8 +32,9 @@ class NWSpellEnchant(NWSpellCheck): 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. + """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: if projectDict is None: