diff --git a/.github/workflows/syntax.yml b/.github/workflows/syntax.yml
index 9371bb99..71e5a4da 100644
--- a/.github/workflows/syntax.yml
+++ b/.github/workflows/syntax.yml
@@ -25,5 +25,5 @@ jobs:
flake8 tests --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Coding Style Violations
run: |
- flake8 nw --count --max-line-length=99 --ignore E203,E221,E226,E228,E241,E251,E261,E266,E302,E305 --show-source --statistics
- flake8 tests --count --max-line-length=99 --ignore E203,E221,E226,E228,E241,E251,E261,E266,E302,E305 --show-source --statistics
+ flake8 nw --count --max-line-length=99 --ignore E203,E221,E226,E228,E241,E251 --show-source --statistics
+ flake8 tests --count --max-line-length=99 --ignore E203,E221,E226,E228,E241,E251 --show-source --statistics
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 288d2b15..04ef9a06 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -77,28 +77,28 @@ The `setup.cfg` file in the root of this project has the following settings for
matches the coding standard:
```conf
[flake8]
-ignore = E203,E221,E226,E228,E241,E251,E261,E266,E302,E305
+ignore = E203,E221,E226,E228,E241,E251
max-line-length = 99
exclude = docs/*
```
The command line equivalent, with reporting, is:
```bash
-flake8 . --count --ignore E203,E221,E226,E228,E241,E251,E261,E266,E302,E305 --max-line-length=99 --show-source --statistics
+flake8 . --count --ignore E203,E221,E226,E228,E241,E251 --max-line-length=99 --show-source --statistics
```
-Passing this check is required before contributions are merged into the `main` branch. This is
-checked automatically when you make a pull request. You can run the `flake8` command locally to
-check beforehand. The full command will give you a detailed description of the code lines that do
-not conform to the standard.
+Passing this check is required before contributions are merged into the `main`, `testing` or `dev`
+branches. This is checked automatically when you make a pull request. You can run the `flake8`
+command locally to check beforehand. The full command will give you a detailed description of the
+code lines that do not conform to the standard.
## Ignored Errors
Some `flake8` error codes are ignored for this project for various reasons. The source also uses
camelCase function and variable names. This is the standard for the Qt libraries novelWriter
-integrates with. It also happens to be the author's personal preferences.
+integrates with. It also happens to be the author's personal preferences. (Yay!)
-The reason behind the other ignored error codes are listed below. Many of them are due to PEP8 not
+The reason behind the other ignored error codes are listed below. Most of them are due to PEP8 not
permitting column alignment as opposed to many other coding styles, like for instance for Go. I
find them useful in regions of bulk value assignments. There's a reason why tables are more
readable than lists. They should be used sparingly though.
@@ -113,10 +113,12 @@ The ignored errors are all `pycodestyle` errors, and they are documented
**Reason:** Column alignment.
**E226:** missing whitespace around arithmetic operator
-**Reason:** This doesn't actually follow the PEP8 recommendation of grouping longer equations by
-operator precedence like `2*a + 3*b` instead of `a * a + 3 * b`. Generally, don't use spaces around
-`*`, `/` and `**`, but _do_ use spaces around `+` and `-`. For appending strings, the spaces can be
-dropped. Don't use the `+` operator for appending multiple strings. Use formatting instead.
+**Reason:** This doesn't actually follow the
+[PEP8 recommendation](https://www.python.org/dev/peps/pep-0008/#other-recommendations)
+of grouping longer equations by operator precedence like `2*a + 3*b` instead of `a * a + 3 * b`.
+Generally, don't use spaces around `*`, `/` and `**`, but _do_ use spaces around `+` and `-`.
+For appending strings, the spaces can be dropped. Don't use the `+` operator for appending multiple
+strings. Use formatting instead.
**E228** missing whitespace around modulo operator
**Reason:** See reason for E226. Formatting `%` like `/` and `*` should be possible.
@@ -126,18 +128,3 @@ dropped. Don't use the `+` operator for appending multiple strings. Use formatti
**E251:** unexpected spaces around keyword / parameter equals
**Reason:** Column alignment.
-
-**E261:** at least two spaces before inline comment
-**Reason:** With syntax highlighting, this one doesn't make much sense.
-
-**E266:** too many leading ‘#’ for block comment
-**Reason:** In the source multiple `#`s is sometimes used to indicate importance or heading level,
-like markdown headers.
-
-**E302:** expected 2 blank lines, found 0
-**Reason:** Applies to classes. Instead, end classes with a comment like `# END Class ClassName` to
-make it easier to see which class just ended. The double line break is then redundant.
-
-**E305:** expected 2 blank lines after end of function or class
-**Reason:** Instead, _always_ end a function with a `return`, preferably indented at function
-level. The end of the function is then clear.
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 477affed..059176af 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
diff --git a/i18n/qtbase.py b/i18n/qtbase.py
index 5b466fc8..795e70d3 100644
--- a/i18n/qtbase.py
+++ b/i18n/qtbase.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Qt Base Translation File
========================
diff --git a/novelWriter.py b/novelWriter.py
index 4f609f24..17e40a09 100755
--- a/novelWriter.py
+++ b/novelWriter.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
"""
novelWriter – Start Script
==========================
@@ -8,9 +7,9 @@ import os
import sys
try:
- import PyQt5.QtWidgets # noqa: F401
- import PyQt5.QtGui # noqa: F401
- import PyQt5.QtCore # noqa: F401
+ import PyQt5.QtWidgets # noqa: F401
+ import PyQt5.QtGui # noqa: F401
+ import PyQt5.QtCore # noqa: F401
except Exception:
print("ERROR: Failed to load dependency PyQt5")
sys.exit(1)
diff --git a/nw/__init__.py b/nw/__init__.py
index 637e1b62..cc126822 100644
--- a/nw/__init__.py
+++ b/nw/__init__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Init File
=======================
@@ -90,15 +89,19 @@ __docurl__ = "https://novelwriter.readthedocs.io"
# Add verbose logging level
VERBOSE = 5
logging.addLevelName(VERBOSE, "VERBOSE")
+
+
def logVerbose(self, message, *args, **kws):
if self.isEnabledFor(VERBOSE):
self._log(VERBOSE, message, args, **kws)
+
logging.Logger.verbose = logVerbose
# Initiating logging
logger = logging.getLogger(__name__)
+
##
# Main Program
##
@@ -106,6 +109,7 @@ logger = logging.getLogger(__name__)
# Load the main config as a global object
CONFIG = Config()
+
def main(sysArgs=None):
"""Parses command line, sets up logging, and launches main GUI.
"""
@@ -229,7 +233,7 @@ def main(sysArgs=None):
errorCode |= 16
try:
- import lxml # noqa: F401
+ import lxml # noqa: F401
except ImportError:
errorData.append("Python module 'lxml' is missing.")
errorCode |= 32
diff --git a/nw/common.py b/nw/common.py
index d093be2d..3def0edd 100644
--- a/nw/common.py
+++ b/nw/common.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Common Functions
==============================
@@ -36,6 +35,7 @@ from nw.constants import nwConst, nwUnicode
logger = logging.getLogger(__name__)
+
def checkString(value, default, allowNone=False):
"""Check if a variable is a string or a none.
"""
@@ -48,6 +48,7 @@ def checkString(value, default, allowNone=False):
return str(value)
return default
+
def checkInt(value, default, allowNone=False):
"""Check if a variable is an integer or a none.
"""
@@ -61,6 +62,7 @@ def checkInt(value, default, allowNone=False):
except Exception:
return default
+
def checkBool(value, default, allowNone=False):
"""Check if a variable is a boolean or a none.
"""
@@ -85,6 +87,7 @@ def checkBool(value, default, allowNone=False):
return default
return default
+
def checkHandle(value, default, allowNone=False):
"""Check if a value is a handle.
"""
@@ -97,6 +100,7 @@ def checkHandle(value, default, allowNone=False):
return str(value)
return default
+
def isHandle(theString):
"""Check if a string is a valid novelWriter handle.
Note: This is case sensitive. Must be lower case!
@@ -110,6 +114,7 @@ def isHandle(theString):
return False
return True
+
def isTitleTag(theString):
"""Check if a string is a valid title string.
"""
@@ -124,21 +129,25 @@ def isTitleTag(theString):
return False
return True
+
def isItemClass(theString):
"""Check if an item is a calid nwItemClass identifier.
"""
return theString in nwItemClass.__members__
+
def isItemType(theString):
"""Check if an item is a calid nwItemType identifier.
"""
return theString in nwItemType.__members__
+
def isItemLayout(theString):
"""Check if an item is a calid nwItemLayout identifier.
"""
return theString in nwItemLayout.__members__
+
def hexToInt(value, default=0):
"""Convert a hex string to an integer.
"""
@@ -149,6 +158,7 @@ def hexToInt(value, default=0):
return default
return default
+
def formatInt(theInt):
"""Formats an integer with k, M, G etc.
"""
@@ -168,6 +178,7 @@ def formatInt(theInt):
return str(theInt)
+
def formatTimeStamp(theTime, fileSafe=False):
"""Take a number (on the format returned by time.time()) and convert
it to a timestamp string.
@@ -177,6 +188,7 @@ def formatTimeStamp(theTime, fileSafe=False):
else:
return datetime.fromtimestamp(theTime).strftime(nwConst.FMT_TSTAMP)
+
def formatTime(tS):
"""Format a time in seconds in HH:MM:SS format or d-HH:MM:SS format
if a full day or longer.
@@ -188,6 +200,7 @@ def formatTime(tS):
return f"{tS//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}"
return "ERROR"
+
def splitVersionNumber(vString):
""" Splits a version string on the form aa.bb.cc into major, minor
and patch, and computes an integer value aabbcc.
@@ -211,6 +224,7 @@ def splitVersionNumber(vString):
return [vMajor, vMinor, vPatch, vInt]
+
def transferCase(theSource, theTarget):
"""Transfers the case of the source word to the target word. This
will consider all upper or lower, and first char capitalisation.
@@ -232,6 +246,7 @@ def transferCase(theSource, theTarget):
return theResult
+
def fuzzyTime(secDiff):
"""Converts a time difference in seconds into a fuzzy time string.
"""
@@ -247,43 +262,43 @@ def fuzzyTime(secDiff):
return QCoreApplication.translate(
"Common", "a minute ago"
)
- elif secDiff < 3300: # 55 minutes
+ elif secDiff < 3300: # 55 minutes
return QCoreApplication.translate(
"Common", "{0} minutes ago"
).format(int(round(secDiff/60)))
- elif secDiff < 5400: # 90 minutes
+ elif secDiff < 5400: # 90 minutes
return QCoreApplication.translate(
"Common", "an hour ago"
)
- elif secDiff < 84600: # 23.5 hours
+ elif secDiff < 84600: # 23.5 hours
return QCoreApplication.translate(
"Common", "{0} hours ago"
).format(int(round(secDiff/3600)))
- elif secDiff < 129600: # 1.5 days
+ elif secDiff < 129600: # 1.5 days
return QCoreApplication.translate(
"Common", "a day ago"
)
- elif secDiff < 561600: # 6.5 days
+ elif secDiff < 561600: # 6.5 days
return QCoreApplication.translate(
"Common", "{0} days ago"
).format(int(round(secDiff/86400)))
- elif secDiff < 907200: # 10.5 days
+ elif secDiff < 907200: # 10.5 days
return QCoreApplication.translate(
"Common", "a week ago"
)
- elif secDiff < 2419200: # 28 days
+ elif secDiff < 2419200: # 28 days
return QCoreApplication.translate(
"Common", "{0} weeks ago"
).format(int(round(secDiff/604800)))
- elif secDiff < 3888000: # 45 days
+ elif secDiff < 3888000: # 45 days
return QCoreApplication.translate(
"Common", "a month ago"
)
- elif secDiff < 29808000: # 345 days
+ elif secDiff < 29808000: # 345 days
return QCoreApplication.translate(
"Common", "{0} months ago"
).format(int(round(secDiff/2592000)))
- elif secDiff < 47336400: # 1.5 years
+ elif secDiff < 47336400: # 1.5 years
return QCoreApplication.translate(
"Common", "a year ago"
)
@@ -292,6 +307,7 @@ def fuzzyTime(secDiff):
"Common", "{0} years ago"
).format(int(round(secDiff/31557600)))
+
def makeFileNameSafe(theText):
"""Returns a filename safe version of the text.
"""
@@ -301,6 +317,7 @@ def makeFileNameSafe(theText):
cleanName += c
return cleanName
+
def getGuiItem(theName):
"""Returns a QtWidget based on its objectName.
"""
@@ -309,6 +326,7 @@ def getGuiItem(theName):
return qWidget
return None
+
def numberToRoman(numVal, isLower=False):
"""Convert an integer to a roman number.
"""
diff --git a/nw/config.py b/nw/config.py
index 16647abd..d7cb9514 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Config Class
==========================
@@ -45,6 +44,7 @@ from nw.constants import nwConst, nwFiles, nwUnicode
logger = logging.getLogger(__name__)
+
class Config:
CNF_STR = 0
@@ -82,27 +82,27 @@ class Config:
self.helpPath = None # The full path to the novelwriter .qhc help file
# Runtime Settings and Variables
- self.confChanged = False # True whenever the config has chenged, false after save
- self.hasHelp = False # True if the Qt help files are present in the assets folder
+ self.confChanged = False # True whenever the config has chenged, false after save
+ self.hasHelp = False # True if the Qt help files are present in the assets folder
- ## General
+ # General
self.guiTheme = "default"
self.guiSyntax = "default_light"
self.guiIcons = "typicons_colour_light"
- self.guiDark = False # Load icons for dark backgrounds, if available
- self.guiFont = "" # Defaults to system default font
- self.guiFontSize = 11 # Is overridden if system default is loaded
- self.guiScale = 1.0 # Set automatically by Theme class
- self.lastNotes = "0x0" # The latest release notes that have been shown
+ self.guiDark = False # Load icons for dark backgrounds, if available
+ self.guiFont = "" # Defaults to system default font
+ self.guiFontSize = 11 # Is overridden if system default is loaded
+ self.guiScale = 1.0 # Set automatically by Theme class
+ self.lastNotes = "0x0" # The latest release notes that have been shown
- ## Localisation
+ # Localisation
self.qLocal = QLocale.system()
self.guiLang = self.qLocal.name()
self.qtLangPath = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
self.nwLangPath = None
self.qtTrans = {}
- ## Sizes
+ # Sizes
self.winGeometry = [1200, 650]
self.prefGeometry = [700, 615]
self.treeColWidth = [200, 50, 30]
@@ -114,54 +114,54 @@ class Config:
self.outlnPanePos = [500, 150]
self.isFullScreen = False
- ## Features
- self.hideVScroll = False # Hide vertical scroll bars on main widgets
- self.hideHScroll = False # Hide horizontal scroll bars on main widgets
+ # Features
+ self.hideVScroll = False # Hide vertical scroll bars on main widgets
+ self.hideHScroll = False # Hide horizontal scroll bars on main widgets
- ## Project
- self.autoSaveProj = 60 # Interval for auto-saving project in seconds
- self.autoSaveDoc = 30 # Interval for auto-saving document in seconds
+ # Project
+ self.autoSaveProj = 60 # Interval for auto-saving project in seconds
+ self.autoSaveDoc = 30 # Interval for auto-saving document in seconds
- ## Text Editor
- self.textFont = None # Editor font
- self.textSize = 12 # Editor font size
- self.textFixedW = True # Keep editor text fixed width
- self.textWidth = 600 # Editor text width
- self.textMargin = 40 # Editor/viewer text margin
- self.tabWidth = 40 # Editor tabulator width
+ # Text Editor
+ self.textFont = None # Editor font
+ self.textSize = 12 # Editor font size
+ self.textFixedW = True # Keep editor text fixed width
+ self.textWidth = 600 # Editor text width
+ self.textMargin = 40 # Editor/viewer text margin
+ self.tabWidth = 40 # Editor tabulator width
- self.focusWidth = 800 # Focus Mode text width
- self.hideFocusFooter = False # Hide document footer in Focus Mode
- self.showFullPath = True # Show full document path in editor header
- self.autoSelect = True # Auto-select word when applying format with no selection
+ self.focusWidth = 800 # Focus Mode text width
+ self.hideFocusFooter = False # Hide document footer in Focus Mode
+ self.showFullPath = True # Show full document path in editor header
+ self.autoSelect = True # Auto-select word when applying format with no selection
- self.doJustify = False # Justify text
- self.showTabsNSpaces = False # Show tabs and spaces in edior
- self.showLineEndings = False # Show line endings in editor
- self.showMultiSpaces = True # Highlight multiple spaces in the text
+ self.doJustify = False # Justify text
+ self.showTabsNSpaces = False # Show tabs and spaces in edior
+ self.showLineEndings = False # Show line endings in editor
+ self.showMultiSpaces = True # Highlight multiple spaces in the text
- self.doReplace = True # Enable auto-replace as you type
- self.doReplaceSQuote = True # Smart single quotes
- self.doReplaceDQuote = True # Smart double quotes
- self.doReplaceDash = True # Replace multiple hyphens with dashes
- self.doReplaceDots = True # Replace three dots with ellipsis
+ self.doReplace = True # Enable auto-replace as you type
+ self.doReplaceSQuote = True # Smart single quotes
+ self.doReplaceDQuote = True # Smart double quotes
+ self.doReplaceDash = True # Replace multiple hyphens with dashes
+ self.doReplaceDots = True # Replace three dots with ellipsis
- self.scrollPastEnd = True # Allow scrolling past end of document
- self.autoScroll = False # Typewriter-like scrolling
- self.autoScrollPos = 30 # Start point for typewriter-like scrolling
+ self.scrollPastEnd = True # Allow scrolling past end of document
+ self.autoScroll = False # Typewriter-like scrolling
+ self.autoScrollPos = 30 # Start point for typewriter-like scrolling
- self.wordCountTimer = 5.0 # Interval for word count update in seconds
- self.bigDocLimit = 800 # Size threshold for heavy editor features in kilobytes
+ self.wordCountTimer = 5.0 # Interval for word count update in seconds
+ self.bigDocLimit = 800 # Size threshold for heavy editor features in kilobytes
- self.highlightQuotes = True # Highlight text in quotes
- self.allowOpenSQuote = False # Allow open-ended single quotes
- self.allowOpenDQuote = True # Allow open-ended double quotes
- self.highlightEmph = True # Add colour to text emphasis
+ self.highlightQuotes = True # Highlight text in quotes
+ self.allowOpenSQuote = False # Allow open-ended single quotes
+ self.allowOpenDQuote = True # Allow open-ended double quotes
+ self.highlightEmph = True # Add colour to text emphasis
- self.stopWhenIdle = True # Stop the status bar clock when the user is idle
- self.userIdleTime = 300 # Time of inactivity to consider user idle
+ self.stopWhenIdle = True # Stop the status bar clock when the user is idle
+ self.userIdleTime = 300 # Time of inactivity to consider user idle
- ## User-Selected Symbols
+ # User-Selected Symbols
self.fmtApostrophe = nwUnicode.U_RSQUO
self.fmtSingleQuotes = [nwUnicode.U_LSQUO, nwUnicode.U_RSQUO]
self.fmtDoubleQuotes = [nwUnicode.U_LDQUO, nwUnicode.U_RDQUO]
@@ -169,11 +169,11 @@ class Config:
self.fmtPadAfter = ""
self.fmtPadThin = False
- ## Spell Checking
+ # Spell Checking
self.spellTool = None
self.spellLanguage = None
- ## Search Bar Switches
+ # Search Bar Switches
self.searchCase = False
self.searchWord = False
self.searchRegEx = False
@@ -181,12 +181,12 @@ class Config:
self.searchNextFile = False
self.searchMatchCap = False
- ## Backup
+ # Backup
self.backupPath = ""
self.backupOnClose = False
self.askBeforeBackup = True
- ## State
+ # State
self.showRefPanel = True
self.viewComments = True
self.viewSynopsis = True
@@ -235,8 +235,8 @@ class Config:
self.kernelVer = "Unknown"
# Packages
- self.hasEnchant = False # The pyenchant package
- self.hasAssistant = False # The Qt Assistant executable
+ self.hasEnchant = False # The pyenchant package
+ self.hasAssistant = False # The Qt Assistant executable
# Recent Cache
self.recentProj = {}
@@ -382,9 +382,9 @@ class Config:
self.qtTrans = {}
langList = [
- (self.qtLangPath, "qtbase"), # Qt 5.x
- (self.nwLangPath, "qtbase"), # Alternative Qt 5.x
- (self.nwLangPath, "nw"), # novelWriter
+ (self.qtLangPath, "qtbase"), # Qt 5.x
+ (self.nwLangPath, "qtbase"), # Alternative Qt 5.x
+ (self.nwLangPath, "nw"), # novelWriter
]
for lngPath, lngBase in langList:
for lngCode in self.qLocal.uiLanguages():
@@ -445,7 +445,7 @@ class Config:
self.errData.append(str(e))
return False
- ## Main
+ # Main
cnfSec = "Main"
self.guiTheme = self._parseLine(
cnfParse, cnfSec, "theme", self.CNF_STR, self.guiTheme
@@ -472,7 +472,7 @@ class Config:
cnfParse, cnfSec, "guilang", self.CNF_STR, self.guiLang
)
- ## Sizes
+ # Sizes
cnfSec = "Sizes"
self.winGeometry = self._parseLine(
cnfParse, cnfSec, "geometry", self.CNF_I_LST, self.winGeometry
@@ -511,7 +511,7 @@ class Config:
cnfParse, cnfSec, "hidehscroll", self.CNF_BOOL, self.hideHScroll
)
- ## Project
+ # Project
cnfSec = "Project"
self.autoSaveProj = self._parseLine(
cnfParse, cnfSec, "autosaveproject", self.CNF_INT, self.autoSaveProj
@@ -520,7 +520,7 @@ class Config:
cnfParse, cnfSec, "autosavedoc", self.CNF_INT, self.autoSaveDoc
)
- ## Editor
+ # Editor
cnfSec = "Editor"
self.textFont = self._parseLine(
cnfParse, cnfSec, "textfont", self.CNF_STR, self.textFont
@@ -631,7 +631,7 @@ class Config:
cnfParse, cnfSec, "useridletime", self.CNF_INT, self.userIdleTime
)
- ## Backup
+ # Backup
cnfSec = "Backup"
self.backupPath = self._parseLine(
cnfParse, cnfSec, "backuppath", self.CNF_STR, self.backupPath
@@ -643,7 +643,7 @@ class Config:
cnfParse, cnfSec, "askbeforebackup", self.CNF_BOOL, self.askBeforeBackup
)
- ## State
+ # State
cnfSec = "State"
self.showRefPanel = self._parseLine(
cnfParse, cnfSec, "showrefpanel", self.CNF_BOOL, self.showRefPanel
@@ -673,7 +673,7 @@ class Config:
cnfParse, cnfSec, "searchmatchcap", self.CNF_BOOL, self.searchMatchCap
)
- ## Path
+ # Path
cnfSec = "Path"
self.lastPath = self._parseLine(
cnfParse, cnfSec, "lastpath", self.CNF_STR, self.lastPath
@@ -704,7 +704,7 @@ class Config:
# Set options
- ## Main
+ # Main
cnfSec = "Main"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "timestamp", formatTimeStamp(time()))
@@ -717,7 +717,7 @@ class Config:
cnfParse.set(cnfSec, "lastnotes", str(self.lastNotes))
cnfParse.set(cnfSec, "guilang", str(self.guiLang))
- ## Sizes
+ # Sizes
cnfSec = "Sizes"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "geometry", self._packList(self.winGeometry))
@@ -733,13 +733,13 @@ class Config:
cnfParse.set(cnfSec, "hidevscroll", str(self.hideVScroll))
cnfParse.set(cnfSec, "hidehscroll", str(self.hideHScroll))
- ## Project
+ # Project
cnfSec = "Project"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "autosaveproject", str(self.autoSaveProj))
cnfParse.set(cnfSec, "autosavedoc", str(self.autoSaveDoc))
- ## Editor
+ # Editor
cnfSec = "Editor"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "textfont", str(self.textFont))
@@ -779,14 +779,14 @@ class Config:
cnfParse.set(cnfSec, "stopwhenidle", str(self.stopWhenIdle))
cnfParse.set(cnfSec, "useridletime", str(self.userIdleTime))
- ## Backup
+ # Backup
cnfSec = "Backup"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "backuppath", str(self.backupPath))
cnfParse.set(cnfSec, "backuponclose", str(self.backupOnClose))
cnfParse.set(cnfSec, "askbeforebackup", str(self.askBeforeBackup))
- ## State
+ # State
cnfSec = "State"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "showrefpanel", str(self.showRefPanel))
@@ -799,7 +799,7 @@ class Config:
cnfParse.set(cnfSec, "searchnextfile", str(self.searchNextFile))
cnfParse.set(cnfSec, "searchmatchcap", str(self.searchMatchCap))
- ## Path
+ # Path
cnfSec = "Path"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "lastpath", str(self.lastPath))
@@ -1119,7 +1119,7 @@ class Config:
"""Cheks if we have the optional packages used by some features.
"""
try:
- import enchant # noqa: F401
+ import enchant # noqa: F401
self.hasEnchant = True
logger.debug("Checking package 'pyenchant': OK")
except Exception:
diff --git a/nw/constants.py b/nw/constants.py
index abf399c5..c80c6adc 100644
--- a/nw/constants.py
+++ b/nw/constants.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Constants
=======================
@@ -28,22 +27,24 @@ from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP
from nw.enum import nwItemClass, nwItemLayout, nwItemType, nwOutline
+
def trConst(tString):
"""Wrapper function for locally translating constants.
"""
return QCoreApplication.translate("Constant", tString)
+
class nwConst():
# Date and Time Formats
- FMT_TSTAMP = "%Y-%m-%d %H:%M:%S" # Default format
- FMT_FSTAMP = "%Y-%m-%d %H.%M.%S" # FileName safe format
- FMT_DSTAMP = "%Y-%m-%d" # Date only format
+ FMT_TSTAMP = "%Y-%m-%d %H:%M:%S" # Default format
+ FMT_FSTAMP = "%Y-%m-%d %H.%M.%S" # FileName safe format
+ FMT_DSTAMP = "%Y-%m-%d" # Date only format
# Various Hard Limits
- MAX_DEPTH = 30 # Maximum folder depth of a project
- MAX_DOCSIZE = 5000000 # Maxium size of a single document
- MAX_BUILDSIZE = 10000000 # Maxium size of a project build
+ MAX_DEPTH = 30 # Maximum folder depth of a project
+ MAX_DOCSIZE = 5000000 # Maxium size of a single document
+ MAX_BUILDSIZE = 10000000 # Maxium size of a project build
# Spell Check Providers
SP_INTERNAL = "internal"
@@ -51,6 +52,7 @@ class nwConst():
# END Class nwConst
+
class nwLists():
"""Lists used for grouping various other constants.
"""
@@ -65,6 +67,7 @@ class nwLists():
# END Class nwLists
+
class nwRegEx():
FMT_EI = r"(?.
+"""
from nw.core.document import NWDoc
from nw.core.index import NWIndex, countWords
diff --git a/nw/core/document.py b/nw/core/document.py
index 7088f61a..70519c2a 100644
--- a/nw/core/document.py
+++ b/nw/core/document.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Document
==============================
@@ -32,6 +31,7 @@ from nw.common import isHandle
logger = logging.getLogger(__name__)
+
class NWDoc():
def __init__(self, theProject, theHandle):
@@ -39,11 +39,11 @@ class NWDoc():
self.theProject = theProject
# Internal Variables
- self._theItem = None # The currently open item
- self._docHandle = None # The handle of the currently open item
- self._fileLoc = None # The file location of the currently open item
- self._docMeta = {} # The meta data of the currently open item
- self._docError = "" # The latest encountered IO error
+ self._theItem = None # The currently open item
+ self._docHandle = None # The handle of the currently open item
+ self._fileLoc = None # The file location of the currently open item
+ self._docMeta = {} # The meta data of the currently open item
+ self._docError = "" # The latest encountered IO error
if isHandle(theHandle):
self._docHandle = theHandle
diff --git a/nw/core/index.py b/nw/core/index.py
index da11e401..8b838d8e 100644
--- a/nw/core/index.py
+++ b/nw/core/index.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Index
===========================
@@ -39,6 +38,7 @@ from nw.core.document import NWDoc
logger = logging.getLogger(__name__)
+
class NWIndex():
H_VALID = ("H0", "H1", "H2", "H3", "H4")
@@ -482,10 +482,10 @@ class NWIndex():
"""Scan a line starting with @ to check that it's valid. Then
split it up into its elements and positions as two arrays.
"""
- theBits = [] # The elements of the string
- thePos = [] # The absolute position of each element
+ theBits = [] # The elements of the string
+ thePos = [] # The absolute position of each element
- aLine = aLine.rstrip() # Remove all trailing white spaces
+ aLine = aLine.rstrip() # Remove all trailing white spaces
nChar = len(aLine)
if nChar < 2:
return False, theBits, thePos
@@ -895,6 +895,7 @@ class NWIndex():
# END Class NWIndex
+
# =============================================================================================== #
# Simple Word Counter
# =============================================================================================== #
diff --git a/nw/core/item.py b/nw/core/item.py
index 6ed3f515..de165b5a 100644
--- a/nw/core/item.py
+++ b/nw/core/item.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Item Class
================================
@@ -33,6 +32,7 @@ from nw.common import checkInt, isHandle, isItemClass, isItemLayout, isItemType
logger = logging.getLogger(__name__)
+
class NWItem():
def __init__(self, theProject):
@@ -51,11 +51,11 @@ class NWItem():
self.isExported = True
# Document Meta Data
- self.charCount = 0 # Current character count
- self.wordCount = 0 # Current word count
- self.paraCount = 0 # Current paragraph count
- self.initCount = 0 # Initial word count
- self.cursorPos = 0 # Last cursor position
+ self.charCount = 0 # Current character count
+ self.wordCount = 0 # Current word count
+ self.paraCount = 0 # Current paragraph count
+ self.initCount = 0 # Initial word count
+ self.cursorPos = 0 # Last cursor position
return
@@ -251,7 +251,7 @@ class NWItem():
if isinstance(expState, str):
self.isExpanded = (expState == str(True))
else:
- self.isExpanded = (expState == True) # noqa: E712
+ self.isExpanded = (expState == True) # noqa: E712
return
def setExported(self, expState):
@@ -260,7 +260,7 @@ class NWItem():
if isinstance(expState, str):
self.isExported = (expState == str(True))
else:
- self.isExported = (expState == True) # noqa: E712
+ self.isExported = (expState == True) # noqa: E712
return
##
diff --git a/nw/core/options.py b/nw/core/options.py
index e9de1af3..bb1d9fbb 100644
--- a/nw/core/options.py
+++ b/nw/core/options.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Options Cache
===================================
@@ -34,6 +33,7 @@ from nw.constants import nwFiles
logger = logging.getLogger(__name__)
+
class OptionState():
def __init__(self, theProject):
diff --git a/nw/core/project.py b/nw/core/project.py
index dcf92822..73c8aee9 100644
--- a/nw/core/project.py
+++ b/nw/core/project.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Wrapper
=============================
@@ -50,6 +49,7 @@ from nw.constants import trConst, nwFiles, nwLabels
logger = logging.getLogger(__name__)
+
class NWProject():
def __init__(self, theParent):
@@ -59,48 +59,48 @@ class NWProject():
self.mainConf = nw.CONFIG
# Core Elements
- self.optState = OptionState(self) # Project-specific GUI options
- self.projTree = NWTree(self) # The project tree
- self.langData = {} # Localisation data
+ self.optState = OptionState(self) # Project-specific GUI options
+ self.projTree = NWTree(self) # The project tree
+ self.langData = {} # Localisation data
# Project Status
- self.projOpened = 0 # The time stamp of when the project file was opened
- self.projChanged = False # The project has unsaved changes
- self.projAltered = False # The project has been altered this session
- self.lockedBy = None # Data on which computer has the project open
- self.saveCount = 0 # Meta data: number of saves
- self.autoCount = 0 # Meta data: number of automatic saves
- self.editTime = 0 # The accumulated edit time read from the project file
+ self.projOpened = 0 # The time stamp of when the project file was opened
+ self.projChanged = False # The project has unsaved changes
+ self.projAltered = False # The project has been altered this session
+ self.lockedBy = None # Data on which computer has the project open
+ self.saveCount = 0 # Meta data: number of saves
+ self.autoCount = 0 # Meta data: number of automatic saves
+ self.editTime = 0 # The accumulated edit time read from the project file
# Class Settings
- self.projPath = None # The full path to where the currently open project is saved
- self.projMeta = None # The full path to the project's meta data folder
- self.projCache = None # The full path to the project's cache folder
- self.projContent = None # The full path to the project's content folder
- self.projDict = None # The spell check dictionary
- self.projSpell = None # The spell check language, if different than default
- self.projLang = None # The project language, used for builds
- self.projFile = None # The file name of the project main XML file
+ self.projPath = None # The full path to where the currently open project is saved
+ self.projMeta = None # The full path to the project's meta data folder
+ self.projCache = None # The full path to the project's cache folder
+ self.projContent = None # The full path to the project's content folder
+ self.projDict = None # The spell check dictionary
+ self.projSpell = None # The spell check language, if different than default
+ self.projLang = None # The project language, used for builds
+ self.projFile = None # The file name of the project main XML file
# Project Meta
- self.projName = "" # Project name (working title)
- self.bookTitle = "" # The final title; should only be used for exports
- self.bookAuthors = [] # A list of book authors
+ self.projName = "" # Project name (working title)
+ self.bookTitle = "" # The final title; should only be used for exports
+ self.bookAuthors = [] # A list of book authors
# Project Settings
- self.autoReplace = {} # Text to auto-replace on exports
- self.titleFormat = {} # The formatting of titles for exports
- self.spellCheck = False # Controls the spellcheck-as-you-type feature
- self.autoOutline = True # If true, the Project Outline is updated automatically
- self.statusItems = None # Novel file progress status values
- self.importItems = None # Note file importance values
- self.lastEdited = None # The handle of the last file to be edited
- self.lastViewed = None # The handle of the last file to be viewed
- self.lastWCount = 0 # The project word count from last session
- self.currWCount = 0 # The project word count in current session
- self.novelWCount = 0 # Total number of words in novel files
- self.notesWCount = 0 # Total number of words in note files
- self.doBackup = True # Run project backup on exit
+ self.autoReplace = {} # Text to auto-replace on exports
+ self.titleFormat = {} # The formatting of titles for exports
+ self.spellCheck = False # Controls the spellcheck-as-you-type feature
+ self.autoOutline = True # If true, the Project Outline is updated automatically
+ self.statusItems = None # Novel file progress status values
+ self.importItems = None # Note file importance values
+ self.lastEdited = None # The handle of the last file to be edited
+ self.lastViewed = None # The handle of the last file to be viewed
+ self.lastWCount = 0 # The project word count from last session
+ self.currWCount = 0 # The project word count in current session
+ self.novelWCount = 0 # Total number of words in novel files
+ self.notesWCount = 0 # Total number of words in note files
+ self.doBackup = True # Run project backup on exit
# Internal Mapping
self.makeAlert = self.theParent.makeAlert
@@ -383,7 +383,7 @@ class NWProject():
# Check for Old Legacy Data
# =========================
- legacyList = [] # Cleanup is done later
+ legacyList = [] # Cleanup is done later
for projItem in os.listdir(self.projPath):
logger.verbose("Project contains: %s" % projItem)
if projItem.startswith("data_"):
diff --git a/nw/core/spellcheck.py b/nw/core/spellcheck.py
index 8b148426..9fcda88f 100644
--- a/nw/core/spellcheck.py
+++ b/nw/core/spellcheck.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Spell Check Classes
=================================
@@ -31,6 +30,7 @@ import difflib
logger = logging.getLogger(__name__)
+
# =============================================================================================== #
# SpellChecking SuperClass
# =============================================================================================== #
@@ -122,6 +122,7 @@ class NWSpellCheck():
# END Class NWSpellCheck
+
# =============================================================================================== #
# Enchant Based SpellChecking
# =============================================================================================== #
@@ -208,6 +209,7 @@ class NWSpellEnchant(NWSpellCheck):
# END Class NWSpellEnchant
+
class FakeEnchant:
"""Fallback for when Enchant is selected, but not installed.
"""
@@ -225,6 +227,7 @@ class FakeEnchant:
# END Class FakeEnchant
+
# =============================================================================================== #
# Fallback SpellChecking Using difflib
# =============================================================================================== #
diff --git a/nw/core/status.py b/nw/core/status.py
index cf0f9fab..b07a8475 100644
--- a/nw/core/status.py
+++ b/nw/core/status.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Item Status Class
=======================================
@@ -32,6 +31,7 @@ from nw.common import checkInt
logger = logging.getLogger(__name__)
+
class NWStatus():
def __init__(self):
diff --git a/nw/core/tohtml.py b/nw/core/tohtml.py
index a205f6b1..c06943d5 100644
--- a/nw/core/tohtml.py
+++ b/nw/core/tohtml.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – HTML Text Converter
=================================
@@ -31,11 +30,12 @@ from nw.constants import nwKeyWords, nwLabels, nwHtmlUnicode
logger = logging.getLogger(__name__)
+
class ToHtml(Tokenizer):
- M_PREVIEW = 0 # Tweak output for the DocViewer
- M_EXPORT = 1 # Tweak output for saving to HTML or printing
- M_EBOOK = 2 # Tweak output for converting to epub
+ M_PREVIEW = 0 # Tweak output for the DocViewer
+ M_EXPORT = 1 # Tweak output for saving to HTML or printing
+ M_EBOOK = 2 # Tweak output for converting to epub
def __init__(self, theProject):
Tokenizer.__init__(self, theProject)
diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py
index 19d09bc3..e78c182b 100644
--- a/nw/core/tokenizer.py
+++ b/nw/core/tokenizer.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Text Tokenizer
============================
@@ -40,6 +39,7 @@ from nw.core.document import NWDoc
logger = logging.getLogger(__name__)
+
class Tokenizer():
# In-Text Format
@@ -51,33 +51,33 @@ class Tokenizer():
FMT_D_E = 6 # End strikeout
# Block Type
- T_EMPTY = 1 # Empty line (new paragraph)
- T_SYNOPSIS = 2 # Synopsis comment
- T_COMMENT = 3 # Comment line
- T_KEYWORD = 4 # Command line
- T_TITLE = 5 # Title
- T_HEAD1 = 6 # Header 1
- T_HEAD2 = 7 # Header 2
- T_HEAD3 = 8 # Header 3
- T_HEAD4 = 9 # Header 4
- T_TEXT = 10 # Text line
- T_SEP = 11 # Scene separator
- T_SKIP = 12 # Paragraph break
+ T_EMPTY = 1 # Empty line (new paragraph)
+ T_SYNOPSIS = 2 # Synopsis comment
+ T_COMMENT = 3 # Comment line
+ T_KEYWORD = 4 # Command line
+ T_TITLE = 5 # Title
+ T_HEAD1 = 6 # Header 1
+ T_HEAD2 = 7 # Header 2
+ T_HEAD3 = 8 # Header 3
+ T_HEAD4 = 9 # Header 4
+ T_TEXT = 10 # Text line
+ T_SEP = 11 # Scene separator
+ T_SKIP = 12 # Paragraph break
# Block Style
- A_NONE = 0x0000 # No special style
- A_LEFT = 0x0001 # Left aligned
- A_RIGHT = 0x0002 # Right aligned
- A_CENTRE = 0x0004 # Centred
- A_JUSTIFY = 0x0008 # Justified
- A_PBB = 0x0010 # Page break before always
- A_PBB_AUT = 0x0020 # Page break before auto
- A_PBA = 0x0040 # Page break after always
- A_PBA_AUT = 0x0080 # Page break after auto
- A_Z_TOPMRG = 0x0100 # Zero top margin
- A_Z_BTMMRG = 0x0200 # Zero bottom margin
- A_IND_L = 0x0400 # Left indentation
- A_IND_R = 0x0800 # Right indentation
+ A_NONE = 0x0000 # No special style
+ A_LEFT = 0x0001 # Left aligned
+ A_RIGHT = 0x0002 # Right aligned
+ A_CENTRE = 0x0004 # Centred
+ A_JUSTIFY = 0x0008 # Justified
+ A_PBB = 0x0010 # Page break before always
+ A_PBB_AUT = 0x0020 # Page break before auto
+ A_PBA = 0x0040 # Page break after always
+ A_PBA_AUT = 0x0080 # Page break after auto
+ A_Z_TOPMRG = 0x0100 # Zero top margin
+ A_Z_BTMMRG = 0x0200 # Zero bottom margin
+ A_IND_L = 0x0400 # Left indentation
+ A_IND_R = 0x0800 # Right indentation
def __init__(self, theProject):
@@ -86,28 +86,28 @@ class Tokenizer():
self.mainConf = nw.CONFIG
# Data Variables
- self.theText = "" # The raw text to be tokenized
- self.theHandle = None # The handle associated with the text
- self.theItem = None # The NWItem associated with the handle
- self.theTokens = [] # The list of the processed tokens
- self.theResult = "" # The result of the last document
+ self.theText = "" # The raw text to be tokenized
+ self.theHandle = None # The handle associated with the text
+ self.theItem = None # The NWItem associated with the handle
+ self.theTokens = [] # The list of the processed tokens
+ self.theResult = "" # The result of the last document
- self.keepMarkdown = False # Whether to keep the markdown text
- self.theMarkdown = [] # The result novelWriter markdown of all documents
+ self.keepMarkdown = False # Whether to keep the markdown text
+ self.theMarkdown = [] # The result novelWriter markdown of all documents
# User Settings
- self.textFont = "Serif" # Output text font
- self.textSize = 11 # Output text size
- self.textFixed = False # Fixed width text
- self.lineHeight = 1.15 # Line height in units of em
- self.blockIndent = 4.00 # Block indent in units of em
- self.doJustify = False # Justify text
- self.doBodyText = True # Include body text
- self.doSynopsis = False # Also process synopsis comments
- self.doComments = False # Also process comments
- self.doKeywords = False # Also process keywords like tags and references
+ self.textFont = "Serif" # Output text font
+ self.textSize = 11 # Output text size
+ self.textFixed = False # Fixed width text
+ self.lineHeight = 1.15 # Line height in units of em
+ self.blockIndent = 4.00 # Block indent in units of em
+ self.doJustify = False # Justify text
+ self.doBodyText = True # Include body text
+ self.doSynopsis = False # Also process synopsis comments
+ self.doComments = False # Also process comments
+ self.doKeywords = False # Also process keywords like tags and references
- ## Margins
+ # Margins
self.marginTitle = (1.000, 0.500)
self.marginHead1 = (1.000, 0.500)
self.marginHead2 = (0.834, 0.500)
@@ -116,23 +116,23 @@ class Tokenizer():
self.marginText = (0.000, 0.584)
self.marginMeta = (0.000, 0.584)
- ## Title Formats
- self.fmtTitle = "%title%" # Formatting for titles
- self.fmtChapter = "%title%" # Formatting for numbered chapters
- self.fmtUnNum = "%title%" # Formatting for unnumbered chapters
- self.fmtScene = "%title%" # Formatting for scenes
- self.fmtSection = "%title%" # Formatting for sections
+ # Title Formats
+ self.fmtTitle = "%title%" # Formatting for titles
+ self.fmtChapter = "%title%" # Formatting for numbered chapters
+ self.fmtUnNum = "%title%" # Formatting for unnumbered chapters
+ self.fmtScene = "%title%" # Formatting for scenes
+ self.fmtSection = "%title%" # Formatting for sections
- self.hideScene = False # Do not include scene headers
- self.hideSection = False # Do not include section headers
+ self.hideScene = False # Do not include scene headers
+ self.hideSection = False # Do not include section headers
- self.linkHeaders = False # Add an anchor before headers
+ self.linkHeaders = False # Add an anchor before headers
# Instance Variables
- self.numChapter = 0 # Counter for chapter numbers
- self.numChScene = 0 # Counter for scene number within chapter
- self.numAbsScene = 0 # Counter for scene number within novel
- self.firstScene = False # Flag to indicate that the first scene of the chapter
+ self.numChapter = 0 # Counter for chapter numbers
+ self.numChScene = 0 # Counter for scene number within chapter
+ self.numAbsScene = 0 # Counter for scene number within novel
+ self.firstScene = False # Flag to indicate that the first scene of the chapter
# This File
self.isNone = False
diff --git a/nw/core/tomd.py b/nw/core/tomd.py
index d95a6810..b66cf902 100644
--- a/nw/core/tomd.py
+++ b/nw/core/tomd.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Markdown Text Converter
=====================================
@@ -31,10 +30,11 @@ from nw.core.tokenizer import Tokenizer
logger = logging.getLogger(__name__)
+
class ToMarkdown(Tokenizer):
- M_STD = 0 # Standard Markdown
- M_GH = 1 # GitHub Markdown
+ M_STD = 0 # Standard Markdown
+ M_GH = 1 # GitHub Markdown
def __init__(self, theProject):
Tokenizer.__init__(self, theProject)
diff --git a/nw/core/toodt.py b/nw/core/toodt.py
index b6dd08fc..3b9aca4b 100644
--- a/nw/core/toodt.py
+++ b/nw/core/toodt.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – ODT Text Converter
================================
@@ -57,38 +56,39 @@ TAG_TAB = "{%s}tab" % XML_NS["text"]
TAG_SPAN = "{%s}span" % XML_NS["text"]
TAG_STNM = "{%s}style-name" % XML_NS["text"]
+
class ToOdt(Tokenizer):
- X_BLD = 0x01 # Bold format
- X_ITA = 0x02 # Italic format
- X_DEL = 0x04 # Strikethrough format
- X_BRK = 0x08 # Line break
- X_TAB = 0x10 # Tab
+ X_BLD = 0x01 # Bold format
+ X_ITA = 0x02 # Italic format
+ X_DEL = 0x04 # Strikethrough format
+ X_BRK = 0x08 # Line break
+ X_TAB = 0x10 # Tab
def __init__(self, theProject, isFlat):
Tokenizer.__init__(self, theProject)
self.mainConf = nw.CONFIG
- self._isFlat = isFlat # Flat: .fodt, otherwise .odt
+ self._isFlat = isFlat # Flat: .fodt, otherwise .odt
- self._dFlat = None # FODT file XML root
- self._dCont = None # ODT content.xml root
- self._dMeta = None # ODT meta.xml root
- self._dStyl = None # ODT styles.xml root
+ self._dFlat = None # FODT file XML root
+ self._dCont = None # ODT content.xml root
+ self._dMeta = None # ODT meta.xml root
+ self._dStyl = None # ODT styles.xml root
- self._xMeta = None # Office meta root
- self._xStyl = None # Office styles root
- self._xAuto = None # Office auto-styles root
- self._xMast = None # Office master-styles root
- self._xBody = None # Office body root
- self._xText = None # Office text root
+ self._xMeta = None # Office meta root
+ self._xStyl = None # Office styles root
+ self._xAuto = None # Office auto-styles root
+ self._xMast = None # Office master-styles root
+ self._xBody = None # Office body root
+ self._xText = None # Office text root
- self._xAut2 = None # Page layout auto-styles for ODT file
+ self._xAut2 = None # Page layout auto-styles for ODT file
- self._mainPara = {} # User-accessible paragraph styles
- self._autoPara = {} # Auto-generated paragraph styles
- self._autoText = {} # Auto-generated text styles
+ self._mainPara = {} # User-accessible paragraph styles
+ self._autoPara = {} # Auto-generated paragraph styles
+ self._autoText = {} # Auto-generated text styles
# Properties
self.textFont = "Liberation Serif"
@@ -114,7 +114,7 @@ class ToOdt(Tokenizer):
self._dLanguage = "en"
self._dCountry = "GB"
- ## Text Margings in Units of em
+ # Text Margings in Units of em
self._mTopTitle = "0.423cm"
self._mTopHead1 = "0.423cm"
self._mTopHead2 = "0.353cm"
@@ -133,13 +133,13 @@ class ToOdt(Tokenizer):
self._mBotText = "0.247cm"
self._mBotMeta = "0.106cm"
- ## Document Margins
+ # Document Margins
self._mDocTop = "2.000cm"
self._mDocBtm = "2.000cm"
self._mDocLeft = "2.000cm"
self._mDocRight = "2.000cm"
- ## Colour
+ # Colour
self._colHead12 = None
self._opaHead12 = None
self._colHead34 = None
@@ -315,15 +315,15 @@ class ToOdt(Tokenizer):
def doConvert(self):
"""Convert the list of text tokens into XML elements.
"""
- self.theResult = "" # Not used, but cleared just in case
+ self.theResult = "" # Not used, but cleared just in case
odtTags = {
- self.FMT_B_B : "_B", # Bold open format
- self.FMT_B_E : "b_", # Bold close format
- self.FMT_I_B : "I", # Italic open format
- self.FMT_I_E : "i", # Italic close format
- self.FMT_D_B : "_S", # Strikethrough open format
- self.FMT_D_E : "s_", # Strikethrough close format
+ self.FMT_B_B : "_B", # Bold open format
+ self.FMT_B_E : "b_", # Bold close format
+ self.FMT_I_B : "I", # Italic open format
+ self.FMT_I_E : "i", # Italic close format
+ self.FMT_D_B : "_S", # Strikethrough open format
+ self.FMT_D_E : "s_", # Strikethrough close format
}
thisPar = []
@@ -985,6 +985,7 @@ class ToOdt(Tokenizer):
# END Class ToOdt
+
# =============================================================================================== #
# Auto-Style Classes
# =============================================================================================== #
@@ -1212,6 +1213,7 @@ class ODTParagraphStyle():
# END Class ODTParagraphStyle
+
class ODTTextStyle():
"""Wrapper class for the text style setting used by the exporter.
Only the used settings are exposed here to keep the class minimal
@@ -1282,6 +1284,7 @@ class ODTTextStyle():
# END Class ODTTextStyle
+
# =============================================================================================== #
# Local Functions
# =============================================================================================== #
diff --git a/nw/core/tree.py b/nw/core/tree.py
index 9a6c3050..6393e42d 100644
--- a/nw/core/tree.py
+++ b/nw/core/tree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Tree Class
================================
@@ -62,22 +61,23 @@ LAYOUT_MAP = {
},
}
+
class NWTree():
def __init__(self, theProject):
self.theProject = theProject
- self._projTree = {} # Holds all the items of the project
- self._treeOrder = [] # The order of the tree items on the tree view
- self._treeRoots = [] # The root items of the tree
- self._trashRoot = None # The handle of the trash root folder
- self._archRoot = None # The handle of the archive root folder
- self._theIndex = 0 # The current iterator index
- self._treeChanged = False # True if tree structure has changed
+ self._projTree = {} # Holds all the items of the project
+ self._treeOrder = [] # The order of the tree items on the tree view
+ self._treeRoots = [] # The root items of the tree
+ self._trashRoot = None # The handle of the trash root folder
+ self._archRoot = None # The handle of the archive root folder
+ self._theIndex = 0 # The current iterator index
+ self._treeChanged = False # True if tree structure has changed
- self._handleSeed = None # Used for generating handles for testing
- self._handleCount = 0 # A counter that is added to the handle generator
+ self._handleSeed = None # Used for generating handles for testing
+ self._handleCount = 0 # A counter that is added to the handle generator
return
diff --git a/nw/dialogs/__init__.py b/nw/dialogs/__init__.py
index 2cb163a4..9f9e5bf8 100644
--- a/nw/dialogs/__init__.py
+++ b/nw/dialogs/__init__.py
@@ -1,4 +1,23 @@
-# -*- coding: utf-8 -*-
+"""
+novelWriter – Dialogs Init
+==========================
+
+This file is a part of novelWriter
+Copyright 2018–2021, 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 .
+"""
from nw.dialogs.about import GuiAbout
from nw.dialogs.docmerge import GuiDocMerge
diff --git a/nw/dialogs/about.py b/nw/dialogs/about.py
index 3ee819bb..28ed76d7 100644
--- a/nw/dialogs/about.py
+++ b/nw/dialogs/about.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI About Box
===========================
@@ -39,6 +38,7 @@ from PyQt5.QtWidgets import (
logger = logging.getLogger(__name__)
+
class GuiAbout(QDialog):
def __init__(self, theParent):
diff --git a/nw/dialogs/docmerge.py b/nw/dialogs/docmerge.py
index 89b8233f..2708bc68 100644
--- a/nw/dialogs/docmerge.py
+++ b/nw/dialogs/docmerge.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Doc Merge Tool
================================
@@ -39,6 +38,7 @@ from nw.gui.custom import QHelpLabel
logger = logging.getLogger(__name__)
+
class GuiDocMerge(QDialog):
def __init__(self, theParent):
diff --git a/nw/dialogs/docsplit.py b/nw/dialogs/docsplit.py
index 02dcd83a..219f1671 100644
--- a/nw/dialogs/docsplit.py
+++ b/nw/dialogs/docsplit.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Doc Split Tool
================================
@@ -40,6 +39,7 @@ from nw.gui.custom import QHelpLabel
logger = logging.getLogger(__name__)
+
class GuiDocSplit(QDialog):
def __init__(self, theParent):
diff --git a/nw/dialogs/itemeditor.py b/nw/dialogs/itemeditor.py
index b8fa07f7..ca27e5ca 100644
--- a/nw/dialogs/itemeditor.py
+++ b/nw/dialogs/itemeditor.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Item Editor
=============================
@@ -39,6 +38,7 @@ from nw.gui.custom import QSwitch
logger = logging.getLogger(__name__)
+
class GuiItemEditor(QDialog):
def __init__(self, theParent, tHandle):
diff --git a/nw/dialogs/preferences.py b/nw/dialogs/preferences.py
index 88022e81..1b2f162c 100644
--- a/nw/dialogs/preferences.py
+++ b/nw/dialogs/preferences.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Preferences
=============================
@@ -43,6 +42,7 @@ from nw.dialogs.quotes import GuiQuoteSelect
logger = logging.getLogger(__name__)
+
class GuiPreferences(PagedDialog):
def __init__(self, theParent):
@@ -134,6 +134,7 @@ class GuiPreferences(PagedDialog):
# END Class GuiPreferences
+
class GuiPreferencesGeneral(QWidget):
def __init__(self, theParent):
@@ -153,7 +154,7 @@ class GuiPreferencesGeneral(QWidget):
self.mainForm.addGroupLabel(self.tr("Look and Feel"))
minWidth = self.mainConf.pxInt(200)
- ## Select Locale
+ # Select Locale
self.guiLang = QComboBox()
self.guiLang.setMinimumWidth(minWidth)
theLangs = self.mainConf.listLanguages(self.mainConf.LANG_NW)
@@ -169,7 +170,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("Changing this requires restarting novelWriter.")
)
- ## Select Theme
+ # Select Theme
self.guiTheme = QComboBox()
self.guiTheme.setMinimumWidth(minWidth)
self.theThemes = self.theTheme.listThemes()
@@ -185,7 +186,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("Changing this requires restarting novelWriter.")
)
- ## Select Icon Theme
+ # Select Icon Theme
self.guiIcons = QComboBox()
self.guiIcons.setMinimumWidth(minWidth)
self.theIcons = self.theTheme.theIcons.listThemes()
@@ -201,7 +202,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("Changing this requires restarting novelWriter.")
)
- ## Dark Icons
+ # Dark Icons
self.guiDark = QSwitch()
self.guiDark.setChecked(self.mainConf.guiDark)
self.mainForm.addRow(
@@ -210,7 +211,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("May improve the look of icons on dark themes.")
)
- ## Font Family
+ # Font Family
self.guiFont = QLineEdit()
self.guiFont.setReadOnly(True)
self.guiFont.setFixedWidth(self.mainConf.pxInt(162))
@@ -225,7 +226,7 @@ class GuiPreferencesGeneral(QWidget):
theButton = self.fontButton
)
- ## Font Size
+ # Font Size
self.guiFontSize = QSpinBox(self)
self.guiFontSize.setMinimum(8)
self.guiFontSize.setMaximum(60)
@@ -319,6 +320,7 @@ class GuiPreferencesGeneral(QWidget):
# END Class GuiPreferencesGeneral
+
class GuiPreferencesProjects(QWidget):
def __init__(self, theParent):
@@ -337,7 +339,7 @@ class GuiPreferencesProjects(QWidget):
# ==============
self.mainForm.addGroupLabel(self.tr("Automatic Save"))
- ## Document Save Timer
+ # Document Save Timer
self.autoSaveDoc = QSpinBox(self)
self.autoSaveDoc.setMinimum(5)
self.autoSaveDoc.setMaximum(600)
@@ -350,7 +352,7 @@ class GuiPreferencesProjects(QWidget):
theUnit=self.tr("seconds")
)
- ## Project Save Timer
+ # Project Save Timer
self.autoSaveProj = QSpinBox(self)
self.autoSaveProj.setMinimum(5)
self.autoSaveProj.setMaximum(600)
@@ -367,7 +369,7 @@ class GuiPreferencesProjects(QWidget):
# ==============
self.mainForm.addGroupLabel(self.tr("Project Backup"))
- ## Backup Path
+ # Backup Path
self.backupPath = self.mainConf.backupPath
self.backupGetPath = QPushButton(self.tr("Browse"))
self.backupGetPath.clicked.connect(self._backupFolder)
@@ -377,7 +379,7 @@ class GuiPreferencesProjects(QWidget):
self.tr("Path: {0}").format(self.backupPath)
)
- ## Run when closing
+ # Run when closing
self.backupOnClose = QSwitch()
self.backupOnClose.setChecked(self.mainConf.backupOnClose)
self.backupOnClose.toggled.connect(self._toggledBackupOnClose)
@@ -387,8 +389,8 @@ class GuiPreferencesProjects(QWidget):
self.tr("Can be overridden for individual projects in Project Settings.")
)
- ## Ask before backup
- ## Only enabled when "Run when closing" is checked
+ # Ask before backup
+ # Only enabled when "Run when closing" is checked
self.askBeforeBackup = QSwitch()
self.askBeforeBackup.setChecked(self.mainConf.askBeforeBackup)
self.askBeforeBackup.setEnabled(self.mainConf.backupOnClose)
@@ -402,7 +404,7 @@ class GuiPreferencesProjects(QWidget):
# =============
self.mainForm.addGroupLabel(self.tr("Session Timer"))
- ## Pause when idle
+ # Pause when idle
self.stopWhenIdle = QSwitch()
self.stopWhenIdle.setChecked(self.mainConf.stopWhenIdle)
self.mainForm.addRow(
@@ -411,7 +413,7 @@ class GuiPreferencesProjects(QWidget):
self.tr("Also pauses when the application window does not have focus.")
)
- ## Inactive time for idle
+ # Inactive time for idle
self.userIdleTime = QDoubleSpinBox()
self.userIdleTime.setMinimum(0.5)
self.userIdleTime.setMaximum(600.0)
@@ -479,6 +481,7 @@ class GuiPreferencesProjects(QWidget):
# END Class GuiPreferencesProjects
+
class GuiPreferencesDocuments(QWidget):
def __init__(self, theParent):
@@ -497,7 +500,7 @@ class GuiPreferencesDocuments(QWidget):
# ==========
self.mainForm.addGroupLabel(self.tr("Text Style"))
- ## Font Family
+ # Font Family
self.textFont = QLineEdit()
self.textFont.setReadOnly(True)
self.textFont.setFixedWidth(self.mainConf.pxInt(162))
@@ -512,7 +515,7 @@ class GuiPreferencesDocuments(QWidget):
theButton = self.fontButton
)
- ## Font Size
+ # Font Size
self.textSize = QSpinBox(self)
self.textSize.setMinimum(8)
self.textSize.setMaximum(60)
@@ -529,7 +532,7 @@ class GuiPreferencesDocuments(QWidget):
# =========
self.mainForm.addGroupLabel(self.tr("Text Flow"))
- ## Max Text Width in Normal Mode
+ # Max Text Width in Normal Mode
self.textWidth = QSpinBox(self)
self.textWidth.setMinimum(300)
self.textWidth.setMaximum(10000)
@@ -542,7 +545,7 @@ class GuiPreferencesDocuments(QWidget):
theUnit=self.tr("px")
)
- ## Max Text Width in Focus Mode
+ # Max Text Width in Focus Mode
self.focusWidth = QSpinBox(self)
self.focusWidth.setMinimum(300)
self.focusWidth.setMaximum(10000)
@@ -555,7 +558,7 @@ class GuiPreferencesDocuments(QWidget):
theUnit=self.tr("px")
)
- ## Document Fixed Width
+ # Document Fixed Width
self.textFixedW = QSwitch()
self.textFixedW.setChecked(not self.mainConf.textFixedW)
self.mainForm.addRow(
@@ -564,7 +567,7 @@ class GuiPreferencesDocuments(QWidget):
self.tr("Text width is defined by the margins only.")
)
- ## Focus Mode Footer
+ # Focus Mode Footer
self.hideFocusFooter = QSwitch()
self.hideFocusFooter.setChecked(self.mainConf.hideFocusFooter)
self.mainForm.addRow(
@@ -573,7 +576,7 @@ class GuiPreferencesDocuments(QWidget):
self.tr("Hide the information bar at the bottom of the document.")
)
- ## Justify Text
+ # Justify Text
self.doJustify = QSwitch()
self.doJustify.setChecked(self.mainConf.doJustify)
self.mainForm.addRow(
@@ -582,7 +585,7 @@ class GuiPreferencesDocuments(QWidget):
self.tr("Lay out text with straight edges in the editor and viewer.")
)
- ## Document Margins
+ # Document Margins
self.textMargin = QSpinBox(self)
self.textMargin.setMinimum(0)
self.textMargin.setMaximum(900)
@@ -595,7 +598,7 @@ class GuiPreferencesDocuments(QWidget):
theUnit=self.tr("px")
)
- ## Tab Width
+ # Tab Width
self.tabWidth = QSpinBox(self)
self.tabWidth.setMinimum(0)
self.tabWidth.setMaximum(200)
@@ -649,6 +652,7 @@ class GuiPreferencesDocuments(QWidget):
# END Class GuiPreferencesDocuments
+
class GuiPreferencesEditor(QWidget):
def __init__(self, theParent):
@@ -669,7 +673,7 @@ class GuiPreferencesEditor(QWidget):
# ==============
self.mainForm.addGroupLabel(self.tr("Spell Checking"))
- ## Spell Check Provider and Language
+ # Spell Check Provider and Language
self.spellLangList = QComboBox(self)
self.spellLangList.setMaximumWidth(mW)
@@ -699,7 +703,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Available languages are determined by your system.")
)
- ## Big Document Size Limit
+ # Big Document Size Limit
self.bigDocLimit = QSpinBox(self)
self.bigDocLimit.setMinimum(10)
self.bigDocLimit.setMaximum(10000)
@@ -716,7 +720,7 @@ class GuiPreferencesEditor(QWidget):
# ==========
self.mainForm.addGroupLabel(self.tr("Word Count"))
- ## Word Count Timer
+ # Word Count Timer
self.wordCountTimer = QDoubleSpinBox(self)
self.wordCountTimer.setDecimals(1)
self.wordCountTimer.setMinimum(2.0)
@@ -734,7 +738,7 @@ class GuiPreferencesEditor(QWidget):
# ==============
self.mainForm.addGroupLabel(self.tr("Writing Guides"))
- ## Show Tabs and Spaces
+ # Show Tabs and Spaces
self.showTabsNSpaces = QSwitch()
self.showTabsNSpaces.setChecked(self.mainConf.showTabsNSpaces)
self.mainForm.addRow(
@@ -743,7 +747,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Add symbols to indicate tabs and spaces in the editor.")
)
- ## Show Line Endings
+ # Show Line Endings
self.showLineEndings = QSwitch()
self.showLineEndings.setChecked(self.mainConf.showLineEndings)
self.mainForm.addRow(
@@ -756,7 +760,7 @@ class GuiPreferencesEditor(QWidget):
# ================
self.mainForm.addGroupLabel(self.tr("Scroll Behaviour"))
- ## Scroll Past End
+ # Scroll Past End
self.scrollPastEnd = QSwitch()
self.scrollPastEnd.setChecked(self.mainConf.scrollPastEnd)
self.mainForm.addRow(
@@ -765,7 +769,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Also improves trypewriter scrolling for short documents.")
)
- ## Typewriter Scrolling
+ # Typewriter Scrolling
self.autoScroll = QSwitch()
self.autoScroll.setChecked(self.mainConf.autoScroll)
self.mainForm.addRow(
@@ -774,7 +778,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Try to keep the cursor at a fixed vertical position.")
)
- ## Typewriter Position
+ # Typewriter Position
self.autoScrollPos = QSpinBox(self)
self.autoScrollPos.setMinimum(10)
self.autoScrollPos.setMaximum(90)
@@ -849,6 +853,7 @@ class GuiPreferencesEditor(QWidget):
# END Class GuiPreferencesEditor
+
class GuiPreferencesSyntax(QWidget):
def __init__(self, theParent):
@@ -973,6 +978,7 @@ class GuiPreferencesSyntax(QWidget):
# END Class GuiPreferencesSyntax
+
class GuiPreferencesAutomation(QWidget):
def __init__(self, theParent):
@@ -991,7 +997,7 @@ class GuiPreferencesAutomation(QWidget):
# ==================
self.mainForm.addGroupLabel(self.tr("Automatic Features"))
- ## Auto-Select Word Under Cursor
+ # Auto-Select Word Under Cursor
self.autoSelect = QSwitch()
self.autoSelect.setChecked(self.mainConf.autoSelect)
self.mainForm.addRow(
@@ -1000,7 +1006,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Apply formatting to word under cursor if no selection is made.")
)
- ## Auto-Replace as You Type Main Switch
+ # Auto-Replace as You Type Main Switch
self.doReplace = QSwitch()
self.doReplace.setChecked(self.mainConf.doReplace)
self.doReplace.toggled.connect(self._toggleAutoReplaceMain)
@@ -1014,7 +1020,7 @@ class GuiPreferencesAutomation(QWidget):
# ===================
self.mainForm.addGroupLabel(self.tr("Replace as You Type"))
- ## Auto-Replace Single Quotes
+ # Auto-Replace Single Quotes
self.doReplaceSQuote = QSwitch()
self.doReplaceSQuote.setChecked(self.mainConf.doReplaceSQuote)
self.doReplaceSQuote.setEnabled(self.mainConf.doReplace)
@@ -1024,7 +1030,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Try to guess which is an opening or a closing single quote.")
)
- ## Auto-Replace Double Quotes
+ # Auto-Replace Double Quotes
self.doReplaceDQuote = QSwitch()
self.doReplaceDQuote.setChecked(self.mainConf.doReplaceDQuote)
self.doReplaceDQuote.setEnabled(self.mainConf.doReplace)
@@ -1034,7 +1040,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Try to guess which is an opening or a closing double quote.")
)
- ## Auto-Replace Hyphens
+ # Auto-Replace Hyphens
self.doReplaceDash = QSwitch()
self.doReplaceDash.setChecked(self.mainConf.doReplaceDash)
self.doReplaceDash.setEnabled(self.mainConf.doReplace)
@@ -1044,7 +1050,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Double and triple hyphens become short and long dashes.")
)
- ## Auto-Replace Dots
+ # Auto-Replace Dots
self.doReplaceDots = QSwitch()
self.doReplaceDots.setChecked(self.mainConf.doReplaceDots)
self.doReplaceDots.setEnabled(self.mainConf.doReplace)
@@ -1058,7 +1064,7 @@ class GuiPreferencesAutomation(QWidget):
# =================
self.mainForm.addGroupLabel(self.tr("Automatic Padding"))
- ## Pad Before
+ # Pad Before
self.fmtPadBefore = QLineEdit()
self.fmtPadBefore.setMaxLength(32)
self.fmtPadBefore.setText(self.mainConf.fmtPadBefore)
@@ -1068,7 +1074,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Automatically add space before any of these symbols."),
)
- ## Pad After
+ # Pad After
self.fmtPadAfter = QLineEdit()
self.fmtPadAfter.setMaxLength(32)
self.fmtPadAfter.setText(self.mainConf.fmtPadAfter)
@@ -1078,7 +1084,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Automatically add space after any of these symbols."),
)
- ## Use Thin Space
+ # Use Thin Space
self.fmtPadThin = QSwitch()
self.fmtPadThin.setChecked(self.mainConf.fmtPadThin)
self.fmtPadThin.setEnabled(self.mainConf.doReplace)
@@ -1129,6 +1135,7 @@ class GuiPreferencesAutomation(QWidget):
# END Class GuiPreferencesAutomation
+
class GuiPreferencesQuotes(QWidget):
def __init__(self, theParent):
@@ -1151,7 +1158,7 @@ class GuiPreferencesQuotes(QWidget):
bWidth = int(2.5*self.theTheme.getTextWidth("..."))
self.quoteSym = {}
- ## Single Quote Style
+ # Single Quote Style
self.quoteSym["SO"] = QLineEdit()
self.quoteSym["SO"].setMaxLength(1)
self.quoteSym["SO"].setReadOnly(True)
@@ -1184,7 +1191,7 @@ class GuiPreferencesQuotes(QWidget):
theButton=self.btnSingleStyleC
)
- ## Double Quote Style
+ # Double Quote Style
self.quoteSym["DO"] = QLineEdit()
self.quoteSym["DO"].setMaxLength(1)
self.quoteSym["DO"].setReadOnly(True)
diff --git a/nw/dialogs/projload.py b/nw/dialogs/projload.py
index 5a5e8de4..f1d3a599 100644
--- a/nw/dialogs/projload.py
+++ b/nw/dialogs/projload.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Open Project
==============================
@@ -43,6 +42,7 @@ from nw.constants import nwFiles
logger = logging.getLogger(__name__)
+
class GuiProjectLoad(QDialog):
NONE_STATE = 0
diff --git a/nw/dialogs/projsettings.py b/nw/dialogs/projsettings.py
index 86bbdbe5..edf84806 100644
--- a/nw/dialogs/projsettings.py
+++ b/nw/dialogs/projsettings.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Project Settings
==================================
@@ -40,6 +39,7 @@ from nw.gui.custom import QSwitch, PagedDialog, QConfigLayout
logger = logging.getLogger(__name__)
+
class GuiProjectSettings(PagedDialog):
def __init__(self, theParent):
@@ -156,6 +156,7 @@ class GuiProjectSettings(PagedDialog):
# END Class GuiProjectSettings
+
class GuiProjectEditMain(QWidget):
def __init__(self, theParent, theProject):
@@ -239,6 +240,7 @@ class GuiProjectEditMain(QWidget):
# END Class GuiProjectEditMain
+
class GuiProjectEditStatus(QWidget):
COL_LABEL = 0
@@ -487,6 +489,7 @@ class GuiProjectEditStatus(QWidget):
# END Class GuiProjectEditStatus
+
class GuiProjectEditReplace(QWidget):
COL_KEY = 0
diff --git a/nw/dialogs/quotes.py b/nw/dialogs/quotes.py
index f1c9bd26..4f81ba29 100644
--- a/nw/dialogs/quotes.py
+++ b/nw/dialogs/quotes.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Quotes Dialog
===============================
@@ -38,6 +37,7 @@ from nw.constants import trConst, nwQuotes
logger = logging.getLogger(__name__)
+
class GuiQuoteSelect(QDialog):
selectedQuote = ""
diff --git a/nw/dialogs/wordlist.py b/nw/dialogs/wordlist.py
index 71442593..e328ecf2 100644
--- a/nw/dialogs/wordlist.py
+++ b/nw/dialogs/wordlist.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI User Wordlist
===============================
@@ -39,6 +38,7 @@ from nw.constants import nwFiles
logger = logging.getLogger(__name__)
+
class GuiWordList(QDialog):
def __init__(self, theParent):
diff --git a/nw/enum.py b/nw/enum.py
index f619d7dd..c0db68a4 100644
--- a/nw/enum.py
+++ b/nw/enum.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Enums
===================
@@ -26,6 +25,7 @@ along with this program. If not, see .
from enum import Enum
+
class nwItemType(Enum):
NO_TYPE = 0
@@ -36,6 +36,7 @@ class nwItemType(Enum):
# END Enum nwItemType
+
class nwItemClass(Enum):
NO_CLASS = 0
@@ -52,6 +53,7 @@ class nwItemClass(Enum):
# END Enum nwItemClass
+
class nwItemLayout(Enum):
NO_LAYOUT = 0
@@ -66,6 +68,7 @@ class nwItemLayout(Enum):
# END Enum nwItemLayout
+
class nwDocAction(Enum):
NO_ACTION = 0
@@ -98,6 +101,7 @@ class nwDocAction(Enum):
# END Enum nwDocAction
+
class nwDocInsert(Enum):
NO_INSERT = 0
@@ -108,6 +112,7 @@ class nwDocInsert(Enum):
# END Enum nwDocInsert
+
class nwAlert(Enum):
INFO = 0
@@ -117,6 +122,7 @@ class nwAlert(Enum):
# END Enum nwAlert
+
class nwState(Enum):
NONE = 0
@@ -125,6 +131,7 @@ class nwState(Enum):
# END Enum nwState
+
class nwWidget(Enum):
TREE = 1
@@ -134,6 +141,7 @@ class nwWidget(Enum):
# END Enum nwWidget
+
class nwOutline(Enum):
TITLE = 0
diff --git a/nw/error.py b/nw/error.py
index 998b7347..74a7c8ea 100644
--- a/nw/error.py
+++ b/nw/error.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Exception Handling
================================
@@ -35,6 +34,7 @@ from PyQt5.QtWidgets import (
logger = logging.getLogger(__name__)
+
# =============================================================================================== #
# Utility Functions
# =============================================================================================== #
@@ -45,6 +45,7 @@ def logException():
exType, exValue, _ = sys.exc_info()
logger.error("%s: %s" % (exType.__name__, str(exValue).strip("'")))
+
# =============================================================================================== #
# Error Handler
# =============================================================================================== #
@@ -151,6 +152,7 @@ class NWErrorMessage(QDialog):
# END Class NWErrorMessage
+
def exceptionHandler(exType, exValue, exTrace):
"""Function to catch unhandled global exceptions.
"""
diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py
index eb87a87f..9c7b3b83 100644
--- a/nw/gui/__init__.py
+++ b/nw/gui/__init__.py
@@ -1,4 +1,23 @@
-# -*- coding: utf-8 -*-
+"""
+novelWriter – GUI Init
+======================
+
+This file is a part of novelWriter
+Copyright 2018–2021, 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 .
+"""
from nw.gui.doceditor import GuiDocEditor
from nw.gui.docviewer import GuiDocViewer, GuiDocViewDetails
diff --git a/nw/gui/custom.py b/nw/gui/custom.py
index 343f3c10..86fd131a 100644
--- a/nw/gui/custom.py
+++ b/nw/gui/custom.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Custom Widgets and Layouts
========================================
@@ -43,6 +42,7 @@ from nw.constants import nwUnicode
logger = logging.getLogger(__name__)
+
# =============================================================================================== #
# Config Form Layout
# =============================================================================================== #
@@ -198,6 +198,7 @@ class QConfigLayout(QGridLayout):
# END Class QConfigLayout
+
class QHelpLabel(QLabel):
def __init__(self, theText, textCol, fontSize=0.9):
@@ -223,6 +224,7 @@ class QHelpLabel(QLabel):
# END Class QHelpLabel
+
# =============================================================================================== #
# Switch Widget
# =============================================================================================== #
@@ -367,6 +369,7 @@ class QSwitch(QAbstractButton):
# END Class QSwitch
+
# =============================================================================================== #
# Paged Dialog w/Custom TabWidget
# =============================================================================================== #
@@ -417,6 +420,7 @@ class PagedDialog(QDialog):
# END Class PagedDialog
+
class VerticalTabBar(QTabBar):
def __init__(self, theParent=None):
diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py
index 32b50ebc..8c2142a8 100644
--- a/nw/gui/doceditor.py
+++ b/nw/gui/doceditor.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Document Editor
=================================
@@ -57,6 +56,7 @@ from nw.gui.dochighlight import GuiDocHighlighter
logger = logging.getLogger(__name__)
+
class GuiDocEditor(QTextEdit):
MOVE_KEYS = (
@@ -84,24 +84,24 @@ class GuiDocEditor(QTextEdit):
self._nwDocument = None
self._nwItem = None
- self._docChanged = False # Flag for changed status of document
- self._docHandle = None # The handle of the open file
- self._docHeaders = [] # Record of headers in the file
+ self._docChanged = False # Flag for changed status of document
+ self._docHandle = None # The handle of the open file
+ self._docHeaders = [] # Record of headers in the file
- self._spellCheck = False # Flag for spell checking enabled
- self._theDict = None # The current spell check dictionary
- self._nonWord = "\"'" # Characters to not include in spell checking
+ self._spellCheck = False # Flag for spell checking enabled
+ self._theDict = None # The current spell check dictionary
+ self._nonWord = "\"'" # Characters to not include in spell checking
# Document Variables
- self._charCount = 0 # Character count
- self._wordCount = 0 # Word count
- self._paraCount = 0 # Paragraph count
- self._lastEdit = 0 # Time stamp of last edit
- self._lastActive = 0 # Time stamp of last activity
- self._lastFind = None # Position of the last found search word
- self._bigDoc = False # Flag for very large document size
- self._doReplace = False # Switch to temporarily disable auto-replace
- self._queuePos = None # Used for delayed change of cursor position
+ self._charCount = 0 # Character count
+ self._wordCount = 0 # Word count
+ self._paraCount = 0 # Paragraph count
+ self._lastEdit = 0 # Time stamp of last edit
+ self._lastActive = 0 # Time stamp of last activity
+ self._lastFind = None # Position of the last found search word
+ self._bigDoc = False # Flag for very large document size
+ self._doReplace = False # Switch to temporarily disable auto-replace
+ self._queuePos = None # Used for delayed change of cursor position
# Typography
self._typDQOpen = '"'
@@ -597,8 +597,8 @@ class GuiDocEditor(QTextEdit):
"""
if self.mainConf.verQtValue >= 50900:
theText = self._qDocument.toRawText()
- theText = theText.replace(nwUnicode.U_LSEP, "\n") # Line separators
- theText = theText.replace(nwUnicode.U_PSEP, "\n") # Paragraph separators
+ theText = theText.replace(nwUnicode.U_LSEP, "\n") # Line separators
+ theText = theText.replace(nwUnicode.U_PSEP, "\n") # Paragraph separators
else:
theText = self.toPlainText()
return theText
@@ -1424,7 +1424,7 @@ class GuiDocEditor(QTextEdit):
theTwo = theText[thePos-2:thePos]
theThree = theText[thePos-3:thePos]
- if not theOne: # Makes Neo sad
+ if not theOne: # Makes Neo sad
return
nDelete = 0
@@ -1931,6 +1931,7 @@ class GuiDocEditor(QTextEdit):
# END Class GuiDocEditor
+
# =============================================================================================== #
# The Off-GUI Thread Word Counter
# A runnable for the word counter to be run in the thread pool off the main GUI thread.
@@ -1960,7 +1961,8 @@ class BackgroundWordCounter(QRunnable):
self._isRunning = False
return
-## END Class BackgroundWordCounter
+# END Class BackgroundWordCounter
+
class BackgroundWordCounterSignals(QObject):
"""The QRunnable cannot emit a signal, so we need a simple QObject
@@ -1970,6 +1972,7 @@ class BackgroundWordCounterSignals(QObject):
# END Class BackgroundWordCounterSignals
+
# =============================================================================================== #
# The Embedded Document Search/Replace Feature
# Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
@@ -2233,7 +2236,7 @@ class GuiDocEditSearch(QFrame):
self._alertSearchValid(theRegEx.isValid())
return theRegEx
- else: # >= 50300 to < 51300
+ else: # >= 50300 to < 51300
if self.isCaseSense:
rxOpt = Qt.CaseSensitive
else:
@@ -2345,6 +2348,7 @@ class GuiDocEditSearch(QFrame):
# END Class GuiDocEditSearch
+
# =============================================================================================== #
# The Embedded Document Header
# Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
@@ -2567,6 +2571,7 @@ class GuiDocEditHeader(QWidget):
# END Class GuiDocEditHeader
+
# =============================================================================================== #
# The Embedded Document Footer
# Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
diff --git a/nw/gui/dochighlight.py b/nw/gui/dochighlight.py
index 95ed4759..4b4eed12 100644
--- a/nw/gui/dochighlight.py
+++ b/nw/gui/dochighlight.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Syntax Highlighter
====================================
@@ -38,6 +37,7 @@ from nw.constants import nwRegEx, nwUnicode
logger = logging.getLogger(__name__)
+
class GuiDocHighlighter(QSyntaxHighlighter):
BLOCK_NONE = 0
@@ -288,7 +288,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
if self.theHandle is None or not theText:
return
- if theText.startswith("@"): # Keywords and commands
+ if theText.startswith("@"): # Keywords and commands
self.setCurrentBlockState(self.BLOCK_META)
tItem = self.theParent.theProject.projTree[self.theHandle]
isValid, theBits, thePos = self.theIndex.scanThis(theText)
@@ -312,27 +312,27 @@ class GuiDocHighlighter(QSyntaxHighlighter):
# so we force a return here
return
- elif theText.startswith("# "): # Header 1
+ elif theText.startswith("# "): # Header 1
self.setCurrentBlockState(self.BLOCK_TITLE)
self.setFormat(0, 1, self.hStyles["header1h"])
self.setFormat(1, len(theText), self.hStyles["header1"])
- elif theText.startswith("## "): # Header 2
+ elif theText.startswith("## "): # Header 2
self.setCurrentBlockState(self.BLOCK_TITLE)
self.setFormat(0, 2, self.hStyles["header2h"])
self.setFormat(2, len(theText), self.hStyles["header2"])
- elif theText.startswith("### "): # Header 3
+ elif theText.startswith("### "): # Header 3
self.setCurrentBlockState(self.BLOCK_TITLE)
self.setFormat(0, 3, self.hStyles["header3h"])
self.setFormat(3, len(theText), self.hStyles["header3"])
- elif theText.startswith("#### "): # Header 4
+ elif theText.startswith("#### "): # Header 4
self.setCurrentBlockState(self.BLOCK_TITLE)
self.setFormat(0, 4, self.hStyles["header4h"])
self.setFormat(4, len(theText), self.hStyles["header4"])
- elif theText.startswith("%"): # Comments
+ elif theText.startswith("%"): # Comments
self.setCurrentBlockState(self.BLOCK_TEXT)
toCheck = theText[1:].lstrip()
synTag = toCheck[:9].lower()
@@ -345,7 +345,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
else:
self.setFormat(0, tLen, self.hStyles["hidden"])
- else: # Text Paragraph
+ else: # Text Paragraph
self.setCurrentBlockState(self.BLOCK_TEXT)
for rX, xFmt in self.rxRules:
rxItt = rX.globalMatch(theText, 0)
diff --git a/nw/gui/docviewer.py b/nw/gui/docviewer.py
index 00cb9ddb..2a82816f 100644
--- a/nw/gui/docviewer.py
+++ b/nw/gui/docviewer.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Document Viewer
=================================
@@ -46,6 +45,7 @@ from nw.constants import nwUnicode
logger = logging.getLogger(__name__)
+
class GuiDocViewer(QTextBrowser):
def __init__(self, theParent):
@@ -571,6 +571,7 @@ class GuiDocViewer(QTextBrowser):
# END Class GuiDocViewer
+
class GuiDocViewHistory():
def __init__(self, docViewer):
@@ -702,6 +703,7 @@ class GuiDocViewHistory():
# END Class GuiDocViewHistory
+
# =============================================================================================== #
# The Embedded Document Header
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
@@ -908,6 +910,7 @@ class GuiDocViewHeader(QWidget):
# END Class GuiDocViewHeader
+
# =============================================================================================== #
# The Embedded Document Footer
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
@@ -1133,6 +1136,7 @@ class GuiDocViewFooter(QWidget):
# END Class GuiDocViewFooter
+
# =============================================================================================== #
# The Document Back-Reference Panel
# Placed in a separate QSplitter position in the main GUI window
diff --git a/nw/gui/itemdetails.py b/nw/gui/itemdetails.py
index 7255affe..9a2b1d30 100644
--- a/nw/gui/itemdetails.py
+++ b/nw/gui/itemdetails.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Item Details Panel
====================================
@@ -36,6 +35,7 @@ from nw.constants import trConst, nwLabels
logger = logging.getLogger(__name__)
+
class GuiItemDetails(QWidget):
def __init__(self, theParent):
@@ -235,10 +235,10 @@ class GuiItemDetails(QWidget):
itStatus = nwItem.itemStatus
if nwItem.itemClass == nwItemClass.NOVEL:
- itStatus = self.theProject.statusItems.checkEntry(itStatus) # Make sure it's valid
+ itStatus = self.theProject.statusItems.checkEntry(itStatus) # Make sure it's valid
flagIcon = self.theParent.statusIcons[itStatus]
else:
- itStatus = self.theProject.importItems.checkEntry(itStatus) # Make sure it's valid
+ itStatus = self.theProject.importItems.checkEntry(itStatus) # Make sure it's valid
flagIcon = self.theParent.importIcons[itStatus]
if nwItem.itemType == nwItemType.FILE:
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index b9cf5e6e..c297380a 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Main Menu
===========================
@@ -36,6 +35,7 @@ from nw.constants import trConst, nwKeyWords, nwLabels, nwUnicode
logger = logging.getLogger(__name__)
+
class GuiMainMenu(QMenuBar):
def __init__(self, theParent):
@@ -241,7 +241,7 @@ class GuiMainMenu(QMenuBar):
self.rootItems[nwItemClass.ARCHIVE] = QAction(self.tr("Outtakes Root"), self.rootMenu)
nCount = 0
for itemClass in self.rootItems.keys():
- nCount += 1 # This forces the lambdas to be unique
+ nCount += 1 # This forces the lambdas to be unique
self.rootItems[itemClass].triggered.connect(
lambda nCount, itemClass=itemClass: self._newTreeItem(nwItemType.ROOT, itemClass)
)
@@ -982,7 +982,7 @@ class GuiMainMenu(QMenuBar):
self.aSpellCheck.setStatusTip(self.tr("Toggle check spelling"))
self.aSpellCheck.setCheckable(True)
self.aSpellCheck.setChecked(self.theProject.spellCheck)
- self.aSpellCheck.triggered.connect(self._toggleSpellCheck) # triggered, not toggled!
+ self.aSpellCheck.triggered.connect(self._toggleSpellCheck) # triggered, not toggled!
self.aSpellCheck.setShortcut("Ctrl+F7")
self.toolsMenu.addAction(self.aSpellCheck)
diff --git a/nw/gui/noveltree.py b/nw/gui/noveltree.py
index fa65de23..dad63610 100644
--- a/nw/gui/noveltree.py
+++ b/nw/gui/noveltree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Novel Tree
============================
@@ -37,6 +36,7 @@ from nw.constants import nwKeyWords
logger = logging.getLogger(__name__)
+
class GuiNovelTree(QTreeWidget):
C_TITLE = 0
diff --git a/nw/gui/outline.py b/nw/gui/outline.py
index 55359e52..88370a19 100644
--- a/nw/gui/outline.py
+++ b/nw/gui/outline.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Project Outline
=================================
@@ -39,6 +38,7 @@ from nw.constants import trConst, nwKeyWords, nwLabels
logger = logging.getLogger(__name__)
+
class GuiOutline(QTreeWidget):
DEF_WIDTH = {
@@ -467,6 +467,7 @@ class GuiOutline(QTreeWidget):
# END Class GuiOutline
+
class GuiOutlineHeaderMenu(QMenu):
def __init__(self, theParent):
diff --git a/nw/gui/outlinedetails.py b/nw/gui/outlinedetails.py
index a4d032b5..ed5b1246 100644
--- a/nw/gui/outlinedetails.py
+++ b/nw/gui/outlinedetails.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Project Outline Details
=========================================
@@ -37,6 +36,7 @@ from nw.constants import trConst, nwKeyWords, nwLabels
logger = logging.getLogger(__name__)
+
class GuiOutlineDetails(QScrollArea):
LVL_MAP = {
diff --git a/nw/gui/projdetails.py b/nw/gui/projdetails.py
index 9fb13ef5..a780ea9f 100644
--- a/nw/gui/projdetails.py
+++ b/nw/gui/projdetails.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Project Details
=================================
@@ -41,6 +40,7 @@ from nw.gui.custom import PagedDialog, QSwitch
logger = logging.getLogger(__name__)
+
class GuiProjectDetails(PagedDialog):
def __init__(self, theParent):
@@ -128,6 +128,7 @@ class GuiProjectDetails(PagedDialog):
# END Class GuiProjectDetails
+
class GuiProjectDetailsMain(QWidget):
def __init__(self, theParent, theProject):
@@ -241,6 +242,7 @@ class GuiProjectDetailsMain(QWidget):
# END Class GuiProjectDetailsMain
+
class GuiProjectDetailsContents(QWidget):
C_TITLE = 0
diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py
index 4f13fd55..c9dbc49e 100644
--- a/nw/gui/projtree.py
+++ b/nw/gui/projtree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Project Tree
==============================
@@ -42,6 +41,7 @@ from nw.constants import nwConst, trConst, nwLists, nwLabels
logger = logging.getLogger(__name__)
+
class GuiProjectTree(QTreeWidget):
C_NAME = 0
@@ -620,10 +620,10 @@ class GuiProjectTree(QTreeWidget):
iStatus = nwItem.itemStatus
if nwItem.itemClass == nwItemClass.NOVEL:
- iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's valid
+ iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's valid
flagIcon = self.theParent.statusIcons[iStatus]
else:
- iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's valid
+ iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's valid
flagIcon = self.theParent.importIcons[iStatus]
trItem.setText(self.C_NAME, nwItem.itemName)
@@ -790,7 +790,7 @@ class GuiProjectTree(QTreeWidget):
selItem = self.itemAt(clickPos)
if isinstance(selItem, QTreeWidgetItem):
tHandle = selItem.data(self.C_NAME, Qt.UserRole)
- self.setSelectedHandle(tHandle) # Just to be safe
+ self.setSelectedHandle(tHandle) # Just to be safe
tItem = self.theProject.projTree[tHandle]
if tItem is not None:
if self.ctxMenu.filterActions(tItem):
@@ -1102,6 +1102,7 @@ class GuiProjectTree(QTreeWidget):
# END Class GuiProjectTree
+
class GuiProjectTreeMenu(QMenu):
def __init__(self, theTree):
diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py
index 85a9f58c..e1fdb8da 100644
--- a/nw/gui/statusbar.py
+++ b/nw/gui/statusbar.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Main Window Status Bar
========================================
@@ -38,6 +37,7 @@ from nw.enum import nwState
logger = logging.getLogger(__name__)
+
class GuiMainStatus(QStatusBar):
def __init__(self, theParent):
@@ -62,7 +62,7 @@ class GuiMainStatus(QStatusBar):
xM = self.mainConf.pxInt(8)
- ## The Spell Checker Language
+ # The Spell Checker Language
self.langIcon = QLabel("")
self.langText = QLabel(self.tr("None"))
self.langIcon.setPixmap(self.theTheme.getPixmap("status_lang", (iPx, iPx)))
@@ -71,7 +71,7 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.langIcon)
self.addPermanentWidget(self.langText)
- ## The Editor Status
+ # The Editor Status
self.docIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
self.docText = QLabel(self.tr("Editor"))
self.docIcon.setContentsMargins(0, 0, 0, 0)
@@ -79,7 +79,7 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.docIcon)
self.addPermanentWidget(self.docText)
- ## The Project Status
+ # The Project Status
self.projIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
self.projText = QLabel(self.tr("Project"))
self.projIcon.setContentsMargins(0, 0, 0, 0)
@@ -87,7 +87,7 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.projIcon)
self.addPermanentWidget(self.projText)
- ## The Project and Session Stats
+ # The Project and Session Stats
self.statsIcon = QLabel()
self.statsText = QLabel("")
self.statsIcon.setPixmap(self.theTheme.getPixmap("status_stats", (iPx, iPx)))
@@ -96,8 +96,8 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.statsIcon)
self.addPermanentWidget(self.statsText)
- ## The Session Clock
- ### Set the mimimum width so the label doesn't rescale every second
+ # The Session Clock
+ # Set the mimimum width so the label doesn't rescale every second
self.timePixmap = self.theTheme.getPixmap("status_time", (iPx, iPx))
self.idlePixmap = self.theTheme.getPixmap("status_idle", (iPx, iPx))
@@ -235,6 +235,7 @@ class GuiMainStatus(QStatusBar):
# END Class GuiMainStatus
+
class StatusLED(QAbstractButton):
def __init__(self, colNone, colGood, colBad, sW, sH, parent=None):
diff --git a/nw/gui/theme.py b/nw/gui/theme.py
index 8f43141d..c94ace19 100644
--- a/nw/gui/theme.py
+++ b/nw/gui/theme.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Theme and Icons Classes
=====================================
@@ -43,6 +42,7 @@ from nw.enum import nwAlert
logger = logging.getLogger(__name__)
+
# =============================================================================================== #
# Gui Theme Class
# Handles the look and feel of novelWriter
@@ -65,8 +65,9 @@ class GuiTheme:
self.syntaxList = []
# Loaded Theme Settings
+ # =====================
- ## Theme
+ # Theme
self.themeName = ""
self.themeDescription = ""
self.themeAuthor = ""
@@ -75,7 +76,7 @@ class GuiTheme:
self.themeLicense = ""
self.themeLicenseUrl = ""
- ## GUI
+ # GUI
self.statNone = [120, 120, 120]
self.statUnsaved = [200, 15, 39]
self.statSaved = [2, 133, 37]
@@ -83,7 +84,7 @@ class GuiTheme:
# Loaded Syntax Settings
- ## Main
+ # Main
self.syntaxName = ""
self.syntaxDescription = ""
self.syntaxAuthor = ""
@@ -92,7 +93,7 @@ class GuiTheme:
self.syntaxLicense = ""
self.syntaxLicenseUrl = ""
- ## Colours
+ # Colours
self.colBack = [255, 255, 255]
self.colText = [0, 0, 0]
self.colLink = [0, 0, 0]
@@ -288,7 +289,7 @@ class GuiTheme:
nw.logException()
return False
- ## Main
+ # Main
cnfSec = "Main"
if confParser.has_section(cnfSec):
self.themeName = self._parseLine(confParser, cnfSec, "name", "")
@@ -299,7 +300,7 @@ class GuiTheme:
self.themeLicense = self._parseLine(confParser, cnfSec, "license", "N/A")
self.themeLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
- ## Palette
+ # Palette
cnfSec = "Palette"
if confParser.has_section(cnfSec):
self._setPalette(confParser, cnfSec, "window", QPalette.Window)
@@ -317,7 +318,7 @@ class GuiTheme:
self._setPalette(confParser, cnfSec, "link", QPalette.Link)
self._setPalette(confParser, cnfSec, "linkvisited", QPalette.LinkVisited)
- ## GUI
+ # GUI
cnfSec = "GUI"
if confParser.has_section(cnfSec):
self.statNone = self._loadColour(confParser, cnfSec, "statusnone")
@@ -346,7 +347,7 @@ class GuiTheme:
nw.logException()
return False
- ## Main
+ # Main
cnfSec = "Main"
if confParser.has_section(cnfSec):
self.syntaxName = self._parseLine(confParser, cnfSec, "name", "")
@@ -357,7 +358,7 @@ class GuiTheme:
self.syntaxLicense = self._parseLine(confParser, cnfSec, "license", "")
self.syntaxLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
- ## Syntax
+ # Syntax
cnfSec = "Syntax"
if confParser.has_section(cnfSec):
self.colBack = self._loadColour(confParser, cnfSec, "background")
@@ -496,6 +497,7 @@ class GuiTheme:
# End Class GuiTheme
+
# =============================================================================================== #
# Icons Class
# =============================================================================================== #
@@ -560,7 +562,7 @@ class GuiIcons:
"search_cancel" : (None, None),
"search_preserve" : (None, None),
- ## General Button Icons
+ # General Button Icons
"folder-open" : (QStyle.SP_DirOpenIcon, "folder-open"),
"delete" : (QStyle.SP_DialogDiscardButton, "edit-delete"),
"close" : (QStyle.SP_DialogCloseButton, "window-close"),
@@ -583,7 +585,7 @@ class GuiIcons:
"forward" : (None, None),
"settings" : (None, None),
- ## Switches
+ # Switches
"sticky-on" : (None, None),
"sticky-off" : (None, None),
"bullet-on" : (None, None),
@@ -651,7 +653,7 @@ class GuiIcons:
nw.logException()
return False
- ## Main
+ # Main
cnfSec = "Main"
if confParser.has_section(cnfSec):
self.themeName = self._parseLine(confParser, cnfSec, "name", "")
@@ -662,7 +664,7 @@ class GuiIcons:
self.themeLicense = self._parseLine(confParser, cnfSec, "license", "N/A")
self.themeLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
- ## Palette
+ # Palette
cnfSec = "Map"
if confParser.has_section(cnfSec):
for iconName, iconFile in confParser.items(cnfSec):
diff --git a/nw/guimain.py b/nw/guimain.py
index 039f1100..337d2904 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Main Window
=============================
@@ -55,6 +54,7 @@ from nw.constants import nwLists
logger = logging.getLogger(__name__)
+
class GuiMain(QMainWindow):
def __init__(self):
@@ -613,9 +613,9 @@ class GuiMain(QMainWindow):
return False
self.treeView.flushTreeOrder()
- nHandle = None # The next handle after tHandle
- fHandle = None # The first file handle we encounter
- foundIt = False # We've found tHandle, pick the next we see
+ nHandle = None # The next handle after tHandle
+ fHandle = None # The first file handle we encounter
+ foundIt = False # We've found tHandle, pick the next we see
for tItem in self.theProject.projTree:
if tItem is None:
continue
diff --git a/nw/tools/__init__.py b/nw/tools/__init__.py
index 18d825d2..0319d6b9 100644
--- a/nw/tools/__init__.py
+++ b/nw/tools/__init__.py
@@ -1,4 +1,23 @@
-# -*- coding: utf-8 -*-
+"""
+novelWriter – Tools Init
+========================
+
+This file is a part of novelWriter
+Copyright 2018–2021, 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 .
+"""
from nw.tools.build import GuiBuildNovel
from nw.tools.projwizard import GuiProjectWizard
diff --git a/nw/tools/build.py b/nw/tools/build.py
index b64fe0bd..2929cd51 100644
--- a/nw/tools/build.py
+++ b/nw/tools/build.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Build Novel Project
=====================================
@@ -52,19 +51,20 @@ from nw.gui.custom import QSwitch
logger = logging.getLogger(__name__)
+
class GuiBuildNovel(QDialog):
- FMT_PDF = 1 # Print to PDF
+ FMT_PDF = 1 # Print to PDF
- FMT_ODT = 2 # Open Document file
- FMT_FODT = 3 # Flat Open Document file
- FMT_HTM = 4 # HTML5
- FMT_NWD = 5 # nW Markdown
- FMT_MD = 6 # Standard Markdown
- FMT_GH = 7 # GitHub Markdown
+ FMT_ODT = 2 # Open Document file
+ FMT_FODT = 3 # Flat Open Document file
+ FMT_HTM = 4 # HTML5
+ FMT_NWD = 5 # nW Markdown
+ FMT_MD = 6 # Standard Markdown
+ FMT_GH = 7 # GitHub Markdown
- FMT_JSON_H = 8 # HTML5 wrapped in JSON
- FMT_JSON_M = 9 # nW Markdown wrapped in JSON
+ FMT_JSON_H = 8 # HTML5 wrapped in JSON
+ FMT_JSON_M = 9 # nW Markdown wrapped in JSON
def __init__(self, theParent):
QDialog.__init__(self, theParent)
@@ -78,10 +78,10 @@ class GuiBuildNovel(QDialog):
self.theProject = theParent.theProject
self.optState = theParent.theProject.optState
- self.htmlText = [] # List of html documents
- self.htmlStyle = [] # List of html styles
- self.htmlSize = 0 # Size of the html document
- self.buildTime = 0 # The timestamp of the last build
+ self.htmlText = [] # List of html documents
+ self.htmlStyle = [] # List of html styles
+ self.htmlSize = 0 # Size of the html document
+ self.buildTime = 0 # The timestamp of the last build
self.setWindowTitle(self.tr("Build Novel Project"))
self.setMinimumWidth(self.mainConf.pxInt(700))
@@ -215,7 +215,7 @@ class GuiBuildNovel(QDialog):
self.fontForm = QGridLayout(self)
self.fontGroup.setLayout(self.fontForm)
- ## Font Family
+ # Font Family
self.textFont = QLineEdit()
self.textFont.setReadOnly(True)
self.textFont.setMinimumWidth(xFmt)
@@ -991,7 +991,7 @@ class GuiBuildNovel(QDialog):
else:
# If the if statements above and here match, it should not
# be possible to reach this else statement.
- return False # pragma: no cover
+ return False # pragma: no cover
# Report to User
# ==============
@@ -1035,7 +1035,7 @@ class GuiBuildNovel(QDialog):
self.textFont.setText(theFont.family())
self.textSize.setValue(theFont.pointSize())
- self.raise_() # Move the dialog to front (fixes a bug on macOS)
+ self.raise_() # Move the dialog to front (fixes a bug on macOS)
return
@@ -1182,6 +1182,7 @@ class GuiBuildNovel(QDialog):
# END Class GuiBuildNovel
+
class GuiBuildNovelDocView(QTextBrowser):
def __init__(self, theParent, theProject):
diff --git a/nw/tools/projwizard.py b/nw/tools/projwizard.py
index 81b885e8..846a67e8 100644
--- a/nw/tools/projwizard.py
+++ b/nw/tools/projwizard.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI New Project Wizard
====================================
@@ -48,6 +47,7 @@ PAGE_POP = 2
PAGE_CUSTOM = 3
PAGE_FINAL = 4
+
class GuiProjectWizard(QWizard):
def __init__(self, theParent):
@@ -86,6 +86,7 @@ class GuiProjectWizard(QWizard):
# END Class GuiProjectWizard
+
class ProjWizardIntroPage(QWizardPage):
def __init__(self, theWizard):
@@ -155,6 +156,7 @@ class ProjWizardIntroPage(QWizardPage):
# END Class ProjWizardIntroPage
+
class ProjWizardFolderPage(QWizardPage):
def __init__(self, theWizard):
@@ -227,6 +229,7 @@ class ProjWizardFolderPage(QWizardPage):
# END Class ProjWizardFolderPage
+
class ProjWizardPopulatePage(QWizardPage):
def __init__(self, theWizard):
@@ -282,6 +285,7 @@ class ProjWizardPopulatePage(QWizardPage):
# END Class ProjWizardPopulatePage
+
class ProjWizardCustomPage(QWizardPage):
def __init__(self, theWizard):
@@ -400,6 +404,7 @@ class ProjWizardCustomPage(QWizardPage):
# END Class ProjWizardCustomPage
+
class ProjWizardFinalPage(QWizardPage):
def __init__(self, theWizard):
diff --git a/nw/tools/writingstats.py b/nw/tools/writingstats.py
index 771870d7..e37c03c7 100644
--- a/nw/tools/writingstats.py
+++ b/nw/tools/writingstats.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Writing Statistics
====================================
@@ -45,6 +44,7 @@ from nw.gui.custom import QSwitch
logger = logging.getLogger(__name__)
+
class GuiWritingStats(QDialog):
C_TIME = 0
@@ -570,7 +570,7 @@ class GuiWritingStats(QDialog):
if isFirst:
# Subtract the offset from the first list entry
dwTotal -= self.wordOffset
- dwTotal = max(dwTotal, 1) # Don't go zero or negative
+ dwTotal = max(dwTotal, 1) # Don't go zero or negative
isFirst = False
if groupByDay:
diff --git a/setup.cfg b/setup.cfg
index 8065eb87..bc11c66e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -49,6 +49,6 @@ gui_scripts =
universal = 0
[flake8]
-ignore = E203,E221,E226,E228,E241,E251,E261,E266,E302,E305
+ignore = E203,E221,E226,E228,E241,E251
max-line-length = 99
exclude = docs/*
diff --git a/setup.py b/setup.py
index 4bb3801f..238590b7 100755
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
"""
novelWriter – Main Setup Script
===============================
@@ -35,6 +34,7 @@ OS_LINUX = 1
OS_WIN = 2
OS_DARWIN = 3
+
# =============================================================================================== #
# Utilities
# =============================================================================================== #
@@ -66,6 +66,7 @@ def extractVersion():
return numVers, hexVers
+
# =============================================================================================== #
# General
# =============================================================================================== #
@@ -102,6 +103,7 @@ def installPackages(hostOS):
return
+
##
# Clean Build and Dist Folders (clean)
##
@@ -140,6 +142,7 @@ def cleanInstall():
return
+
# =============================================================================================== #
# Additional Buiilds
# =============================================================================================== #
@@ -217,6 +220,7 @@ def buildQtDocs():
return
+
##
# Qt Linguist QM Builder (qtlrelease)
##
@@ -255,6 +259,7 @@ def buildQtI18n():
return
+
##
# Qt Linguist TS Builder (qtlupdate)
##
@@ -278,6 +283,7 @@ def buildQtI18nTS():
return
+
##
# Sample Project ZIP File Builder (sample)
##
@@ -318,6 +324,7 @@ def buildSampleZip():
return
+
# =============================================================================================== #
# Python Packaging
# =============================================================================================== #
@@ -429,6 +436,7 @@ def makeMinimalPackage(targetOS):
return
+
##
# Make Simple Package (pack-pyz)
##
@@ -607,6 +615,7 @@ def makeSimplePackage(embedPython):
return
+
# =============================================================================================== #
# General Installers
# =============================================================================================== #
@@ -754,6 +763,7 @@ def xdgInstall():
return
+
##
# XDG Uninstallation (xdg-uninstall)
##
@@ -823,6 +833,7 @@ def xdgUninstall():
return
+
##
# WIN Installation (win-install)
##
@@ -947,6 +958,7 @@ def winInstall():
return
+
##
# WIN Uninstallation (win-uninstall)
##
@@ -1033,6 +1045,7 @@ def winUninstall():
return
+
# =============================================================================================== #
# Windows Installers
# =============================================================================================== #
@@ -1070,6 +1083,7 @@ def innoSetup():
return
+
# =============================================================================================== #
# Process Command Line
# =============================================================================================== #
@@ -1280,7 +1294,7 @@ if __name__ == "__main__":
sys.exit(0)
# Run the standard setup
- import setuptools # noqa: F401
+ import setuptools # noqa: F401
setuptools.setup()
# END Main
diff --git a/tests/conftest.py b/tests/conftest.py
index 7459f21a..8db6da21 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Test Suite Configuration
======================================
@@ -30,9 +29,10 @@ from tools import cleanProject
sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
-import nw # noqa: E402
+import nw # noqa: E402
+
+from nw.config import Config # noqa: E402
-from nw.config import Config # noqa: E402
##
# Core Test Folders
@@ -52,6 +52,7 @@ def tmpDir():
os.mkdir(theDir)
return theDir
+
@pytest.fixture(scope="session")
def refDir():
"""The folder where all the reference files are stored for verifying
@@ -61,6 +62,7 @@ def refDir():
theDir = os.path.join(testDir, "reference")
return theDir
+
@pytest.fixture(scope="session")
def filesDir():
"""The folder where additional test files are stored.
@@ -69,6 +71,7 @@ def filesDir():
theDir = os.path.join(testDir, "files")
return theDir
+
@pytest.fixture(scope="session")
def outDir(tmpDir):
"""An output folder for test results
@@ -78,6 +81,7 @@ def outDir(tmpDir):
os.mkdir(theDir)
return theDir
+
@pytest.fixture(scope="function")
def fncDir(tmpDir):
"""A temporary folder for a single test function.
@@ -92,6 +96,7 @@ def fncDir(tmpDir):
shutil.rmtree(fncDir)
return
+
@pytest.fixture(scope="function")
def fncProj(fncDir):
"""A temporary folder for a single test function,
@@ -104,6 +109,7 @@ def fncProj(fncDir):
os.mkdir(prjDir)
return prjDir
+
##
# novelWriter Objects
##
@@ -121,6 +127,7 @@ def tmpConf(tmpDir):
theConf.guiLang = "en_GB"
return theConf
+
@pytest.fixture(scope="function")
def fncConf(fncDir):
"""Create a temporary novelWriter configuration object.
@@ -134,6 +141,7 @@ def fncConf(fncDir):
theConf.guiLang = "en_GB"
return theConf
+
@pytest.fixture(scope="function")
def dummyGUI(monkeypatch, tmpConf):
"""Create a mock instance of novelWriter's main GUI class.
@@ -143,6 +151,7 @@ def dummyGUI(monkeypatch, tmpConf):
theGui.mainConf = tmpConf
return theGui
+
@pytest.fixture(scope="function")
def nwGUI(qtbot, monkeypatch, fncDir, fncConf):
"""Create an instance of the novelWriter GUI.
@@ -164,6 +173,7 @@ def nwGUI(qtbot, monkeypatch, fncDir, fncConf):
return
+
##
# Temp Project Folders
##
@@ -188,6 +198,7 @@ def nwMinimal(tmpDir):
return
+
@pytest.fixture(scope="function")
def nwLipsum(tmpDir):
"""A medium sized novelWriter example project with a lot of Lorem
@@ -209,6 +220,7 @@ def nwLipsum(tmpDir):
return
+
@pytest.fixture(scope="function")
def nwOldProj(tmpDir):
"""A minimal movelWriter project using the old folder structure used
diff --git a/tests/mock.py b/tests/mock.py
index eb76e5a6..c87a95ad 100644
--- a/tests/mock.py
+++ b/tests/mock.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Test Suite Mocked Classes
=======================================
@@ -20,6 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+
# =========================================================================== #
# Mock GUI
# =========================================================================== #
@@ -79,6 +79,7 @@ class MockGuiMain():
# END Class MockGuiMain
+
class MockStatusBar():
def __init__(self):
@@ -92,6 +93,7 @@ class MockStatusBar():
# END Class MockStatusBar
+
class MockApp:
def __init__(self):
@@ -102,6 +104,7 @@ class MockApp:
# END Class MockApp
+
# =========================================================================== #
# Error Functions
# Mock functions that will raise errors instead.
@@ -110,5 +113,6 @@ class MockApp:
def causeOSError(*args, **kwargs):
raise OSError("OSError")
+
def causeException(*args, **kwargs):
raise Exception("Exception")
diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py
index a5698685..e5fb98ce 100644
--- a/tests/test_base/test_base_common.py
+++ b/tests/test_base/test_base_common.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Common Functions Tester
=====================================
@@ -30,6 +29,7 @@ from nw.common import (
isItemLayout, numberToRoman
)
+
@pytest.mark.base
def testBaseCommon_CheckString():
"""Test the checkString function.
@@ -44,6 +44,7 @@ def testBaseCommon_CheckString():
# END Test testBaseCommon_CheckString
+
@pytest.mark.base
def testBaseCommon_CheckInt():
"""Test the checkInt function.
@@ -57,6 +58,7 @@ def testBaseCommon_CheckInt():
# END Test testBaseCommon_CheckInt
+
@pytest.mark.base
def testBaseCommon_CheckBool():
"""Test the checkBool function.
@@ -75,6 +77,7 @@ def testBaseCommon_CheckBool():
# END Test testBaseCommon_CheckBool
+
@pytest.mark.base
def testBaseCommon_CheckHandle():
"""Test the checkHandle function.
@@ -88,6 +91,7 @@ def testBaseCommon_CheckHandle():
# END Test testBaseCommon_CheckHandle
+
@pytest.mark.base
def testBaseCommon_IsHandle():
"""Test the isHandle function.
@@ -102,6 +106,7 @@ def testBaseCommon_IsHandle():
# END Test testBaseCommon_IsHandle
+
@pytest.mark.base
def testBaseCommon_IsTitleTag():
"""Test the isItemClass function.
@@ -119,6 +124,7 @@ def testBaseCommon_IsTitleTag():
# END Test testBaseCommon_IsTitleTag
+
@pytest.mark.base
def testBaseCommon_IsItemClass():
"""Test the isItemClass function.
@@ -141,6 +147,7 @@ def testBaseCommon_IsItemClass():
# END Test testBaseCommon_IsItemClass
+
@pytest.mark.base
def testBaseCommon_IsItemType():
"""Test the isItemType function.
@@ -157,6 +164,7 @@ def testBaseCommon_IsItemType():
# END Test testBaseCommon_IsItemType
+
@pytest.mark.base
def testBaseCommon_IsItemLayout():
"""Test the isItemLayout function.
@@ -177,6 +185,7 @@ def testBaseCommon_IsItemLayout():
# END Test testBaseCommon_IsItemLayout
+
@pytest.mark.base
def testBaseCommon_HexToInt():
"""Test the hexToInt function.
@@ -190,6 +199,7 @@ def testBaseCommon_HexToInt():
# END Test testBaseCommon_HexToInt
+
@pytest.mark.base
def testBaseCommon_FormatTimeStamp():
"""Test the formatTimeStamp function.
@@ -200,6 +210,7 @@ def testBaseCommon_FormatTimeStamp():
# END Test testBaseCommon_FormatTimeStamp
+
@pytest.mark.base
def testBaseCommon_FormatTime():
"""Test the formatTime function.
@@ -222,6 +233,7 @@ def testBaseCommon_FormatTime():
# END Test testBaseCommon_FormatTime
+
@pytest.mark.base
def testBaseCommon_FormatInt():
"""Test the formatInt function.
@@ -237,6 +249,7 @@ def testBaseCommon_FormatInt():
# END Test testBaseCommon_FormatInt
+
@pytest.mark.base
def testBaseCommon_TransferCase():
"""Test the transferCase function.
@@ -251,6 +264,7 @@ def testBaseCommon_TransferCase():
# END Test testBaseCommon_TransferCase
+
@pytest.mark.base
def testBaseCommon_FuzzyTime():
"""Test the fuzzyTime function.
@@ -286,6 +300,7 @@ def testBaseCommon_FuzzyTime():
# END Test testBaseCommon_FuzzyTime
+
@pytest.mark.base
def testBaseCommon_MakeFileNameSafe():
"""Test the fuzzyTime function.
@@ -297,6 +312,7 @@ def testBaseCommon_MakeFileNameSafe():
# END Test testBaseCommon_MakeFileNameSafe
+
@pytest.mark.core
def testBaseCommon_RomanNumbers():
"""Test conversion of integers to Roman numbers.
diff --git a/tests/test_base/test_base_config.py b/tests/test_base/test_base_config.py
index aaedc4af..14e24ec3 100644
--- a/tests/test_base/test_base_config.py
+++ b/tests/test_base/test_base_config.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Config Class Tester
=================================
@@ -33,6 +32,7 @@ from tools import cmpFiles, writeFile
from nw.config import Config
from nw.constants import nwConst, nwFiles
+
@pytest.mark.base
def testBaseConfig_Constructor(monkeypatch):
"""Test config contructor.
@@ -79,6 +79,7 @@ def testBaseConfig_Constructor(monkeypatch):
# END Test testBaseConfig_Constructor
+
@pytest.mark.base
def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
"""Test config intialisation.
@@ -95,7 +96,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
# Let the config class figure out the path
with monkeypatch.context() as mp:
- mp.setattr("PyQt5.QtCore.QStandardPaths.writableLocation", lambda *args: fncDir)
+ mp.setattr("PyQt5.QtCore.QStandardPaths.writableLocation", lambda *a: fncDir)
tstConf.verQtValue = 50600
tstConf.initConfig()
assert tstConf.confPath == os.path.join(fncDir, tstConf.appHandle)
@@ -132,7 +133,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
# Run again and set the paths directly and correctly
# This should create a config file as well
with monkeypatch.context() as mp:
- mp.setattr("os.path.expanduser", lambda *args: "")
+ mp.setattr("os.path.expanduser", lambda *a: "")
tstConf.spellTool = nwConst.SP_INTERNAL
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
assert tstConf.confPath == tmpDir
@@ -205,6 +206,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
# END Test testBaseConfig_Init
+
@pytest.mark.base
def testBaseConfig_RecentCache(monkeypatch, tmpConf, tmpDir, fncDir):
"""Test recent cache file.
@@ -266,6 +268,7 @@ def testBaseConfig_RecentCache(monkeypatch, tmpConf, tmpDir, fncDir):
# END Test testBaseConfig_RecentCache
+
@pytest.mark.base
def testBaseConfig_SetPath(tmpConf, tmpDir):
"""Test path setters.
@@ -297,6 +300,7 @@ def testBaseConfig_SetPath(tmpConf, tmpDir):
# END Test testBaseConfig_SetPath
+
@pytest.mark.base
def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir):
"""Set various sizes and positions
@@ -470,6 +474,7 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir):
# END Test testBaseConfig_SettersGetters
+
@pytest.mark.base
def testBaseConfig_Internal(monkeypatch, tmpConf):
"""Check internal functions.
diff --git a/tests/test_base/test_base_error.py b/tests/test_base/test_base_error.py
index 29bec978..03cbbb5d 100644
--- a/tests/test_base/test_base_error.py
+++ b/tests/test_base/test_base_error.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Error Handler Tester
==================================
@@ -29,6 +28,7 @@ from mock import causeException
from nw.error import NWErrorMessage, exceptionHandler
+
@pytest.mark.base
def testBaseError_Dialog(qtbot, monkeypatch, fncDir, tmpDir):
"""Test the error dialog.
@@ -71,6 +71,7 @@ def testBaseError_Dialog(qtbot, monkeypatch, fncDir, tmpDir):
# END Test testBaseError_Dialog
+
@pytest.mark.base
def testBaseError_Handler(qtbot, monkeypatch, fncDir, tmpDir):
"""Test the error handler. This test doesn'thave any asserts, but it
@@ -85,28 +86,28 @@ def testBaseError_Handler(qtbot, monkeypatch, fncDir, tmpDir):
# Normal shutdown
with monkeypatch.context() as mp:
- mp.setattr(NWErrorMessage, "exec_", lambda *args: None)
- mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None)
+ mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
+ mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
exceptionHandler(Exception, "Error Message", None)
# Should not crash when no GUI is found
with monkeypatch.context() as mp:
- mp.setattr(NWErrorMessage, "exec_", lambda *args: None)
- mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None)
+ mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
+ mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", lambda: [])
exceptionHandler(Exception, "Error Message", None)
# Should handle qApp failing
with monkeypatch.context() as mp:
- mp.setattr(NWErrorMessage, "exec_", lambda *args: None)
- mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None)
+ mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
+ mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", causeException)
exceptionHandler(Exception, "Error Message", None)
# Should handle failing to close main GUI
with monkeypatch.context() as mp:
- mp.setattr(NWErrorMessage, "exec_", lambda *args: None)
- mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None)
+ mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
+ mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
mp.setattr(nwGUI, "closeMain", causeException)
exceptionHandler(Exception, "Error Message", None)
diff --git a/tests/test_base/test_base_init.py b/tests/test_base/test_base_init.py
index 2bcf9a61..a0b2cf70 100644
--- a/tests/test_base/test_base_init.py
+++ b/tests/test_base/test_base_init.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Main Init Tester
==============================
@@ -27,6 +26,7 @@ import sys
from mock import MockGuiMain
+
@pytest.mark.base
def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
"""Check launching the main GUI.
@@ -64,6 +64,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
# END Test testBaseInit_Launch
+
@pytest.mark.base
def testBaseInit_Options(monkeypatch, tmpDir):
"""Test command line options for logging level.
@@ -136,6 +137,7 @@ def testBaseInit_Options(monkeypatch, tmpDir):
# END Test testBaseInit_Options
+
@pytest.mark.base
def testBaseInit_Imports(caplog, monkeypatch, tmpDir):
"""Check import error handling.
@@ -156,10 +158,10 @@ def testBaseInit_Imports(caplog, monkeypatch, tmpDir):
["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
)
- assert ex.value.code & 4 == 4 # Python version not satisfied
- assert ex.value.code & 8 == 8 # Qt version not satisfied
- assert ex.value.code & 16 == 16 # PyQt version not satisfied
- assert ex.value.code & 32 == 32 # lxml package missing
+ assert ex.value.code & 4 == 4 # Python version not satisfied
+ assert ex.value.code & 8 == 8 # Qt version not satisfied
+ assert ex.value.code & 16 == 16 # PyQt version not satisfied
+ assert ex.value.code & 32 == 32 # lxml package missing
assert "At least Python" in caplog.messages[0]
assert "At least Qt5" in caplog.messages[1]
diff --git a/tests/test_core/test_core_document.py b/tests/test_core/test_core_document.py
index 42df9d1c..f165655b 100644
--- a/tests/test_core/test_core_document.py
+++ b/tests/test_core/test_core_document.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – NWDoc Class Tester
================================
@@ -28,6 +27,7 @@ from mock import causeOSError
from nw.core import NWProject, NWDoc
from nw.enum import nwItemClass, nwItemLayout
+
@pytest.mark.core
def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal):
"""Test loading and saving a document with the NWDoc class.
@@ -120,8 +120,9 @@ def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal):
# END Test testCoreDocument_Load
+
@pytest.mark.core
-def testCoreDocument_Methods(monkeypatch, dummyGUI, nwMinimal):
+def testCoreDocument_Methods(dummyGUI, nwMinimal):
"""Test other methods of the NWDoc class.
"""
theProject = NWProject(dummyGUI)
diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py
index 0fdde671..4dcbbfd2 100644
--- a/tests/test_core/test_core_index.py
+++ b/tests/test_core/test_core_index.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – NWIndex Class Tester
==================================
@@ -33,6 +32,7 @@ from nw.core.project import NWProject
from nw.core.index import NWIndex, countWords
from nw.enum import nwItemClass, nwItemLayout
+
@pytest.mark.core
def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir):
"""Test core functionality of scaning, saving, loading and checking
@@ -50,12 +50,12 @@ def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir):
theIndex = NWIndex(theProject)
notIndexable = {
- "b3643d0f92e32": False, # Novel ROOT
- "45e6b01ca35c1": False, # Chapter One FOLDER
- "6bd935d2490cd": False, # Chapter Two FOLDER
- "67a8707f2f249": False, # Character ROOT
- "6c6afb1247750": False, # Plot ROOT
- "60bdf227455cc": False, # World ROOT
+ "b3643d0f92e32": False, # Novel ROOT
+ "45e6b01ca35c1": False, # Chapter One FOLDER
+ "6bd935d2490cd": False, # Chapter Two FOLDER
+ "67a8707f2f249": False, # Character ROOT
+ "6c6afb1247750": False, # Plot ROOT
+ "60bdf227455cc": False, # World ROOT
}
for tItem in theProject.projTree:
assert theIndex.reIndexHandle(tItem.itemHandle) is notIndexable.get(tItem.itemHandle, True)
@@ -124,6 +124,7 @@ def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir):
# END Test testCoreIndex_LoadSave
+
@pytest.mark.core
def testCoreIndex_ScanThis(nwMinimal, dummyGUI):
"""Test the tag scanner function scanThis.
@@ -175,6 +176,7 @@ def testCoreIndex_ScanThis(nwMinimal, dummyGUI):
# END Test testCoreIndex_ScanThis
+
@pytest.mark.core
def testCoreIndex_CheckThese(nwMinimal, dummyGUI):
"""Test the tag checker function checkThese.
@@ -202,7 +204,7 @@ def testCoreIndex_CheckThese(nwMinimal, dummyGUI):
assert theIndex.scanText(nHandle, (
"# Hello World!\n"
"@pov: Jane\n"
- "@invalid: John\n" # Checks for issue #688
+ "@invalid: John\n" # Checks for issue #688
))
assert theIndex._tagIndex == {"Jane": [2, cHandle, "CHARACTER", "T000001"]}
assert theIndex.getNovelData(nHandle, "T000001")["title"] == "Hello World!"
@@ -236,6 +238,7 @@ def testCoreIndex_CheckThese(nwMinimal, dummyGUI):
# END Test testCoreIndex_CheckThese
+
@pytest.mark.core
def testCoreIndex_ScanText(nwMinimal, dummyGUI):
"""Check the index text scanner.
@@ -309,29 +312,29 @@ def testCoreIndex_ScanText(nwMinimal, dummyGUI):
"#### Title Four\n\n"
"% synopsis: Synopsis Four.\n\n"
"Paragraph Four.\n\n"
- "##### Title Five\n\n" # Not interpreted as a title, the hashes are counted as a word
+ "##### Title Five\n\n" # Not interpreted as a title, the hashes are counted as a word
"Paragraph Five.\n\n"
))
- assert theIndex._refIndex[nHandle].get("T000000", None) is not None # Always there
- assert theIndex._refIndex[nHandle].get("T000001", None) is not None # Heading 1
+ assert theIndex._refIndex[nHandle].get("T000000", None) is not None # Always there
+ assert theIndex._refIndex[nHandle].get("T000001", None) is not None # Heading 1
assert theIndex._refIndex[nHandle].get("T000002", None) is None
assert theIndex._refIndex[nHandle].get("T000003", None) is None
assert theIndex._refIndex[nHandle].get("T000004", None) is None
assert theIndex._refIndex[nHandle].get("T000005", None) is None
assert theIndex._refIndex[nHandle].get("T000006", None) is None
- assert theIndex._refIndex[nHandle].get("T000007", None) is not None # Heading 2
+ assert theIndex._refIndex[nHandle].get("T000007", None) is not None # Heading 2
assert theIndex._refIndex[nHandle].get("T000008", None) is None
assert theIndex._refIndex[nHandle].get("T000009", None) is None
assert theIndex._refIndex[nHandle].get("T000010", None) is None
assert theIndex._refIndex[nHandle].get("T000011", None) is None
assert theIndex._refIndex[nHandle].get("T000012", None) is None
- assert theIndex._refIndex[nHandle].get("T000013", None) is not None # Heading 3
+ assert theIndex._refIndex[nHandle].get("T000013", None) is not None # Heading 3
assert theIndex._refIndex[nHandle].get("T000014", None) is None
assert theIndex._refIndex[nHandle].get("T000015", None) is None
assert theIndex._refIndex[nHandle].get("T000016", None) is None
assert theIndex._refIndex[nHandle].get("T000017", None) is None
assert theIndex._refIndex[nHandle].get("T000018", None) is None
- assert theIndex._refIndex[nHandle].get("T000019", None) is not None # Heading 4
+ assert theIndex._refIndex[nHandle].get("T000019", None) is not None # Heading 4
assert theIndex._refIndex[nHandle].get("T000020", None) is None
assert theIndex._refIndex[nHandle].get("T000021", None) is None
assert theIndex._refIndex[nHandle].get("T000022", None) is None
@@ -400,9 +403,9 @@ def testCoreIndex_ScanText(nwMinimal, dummyGUI):
assert theIndex.scanText(sHandle, (
"# Title One\n\n"
- "@pov: One\n\n" # Valid
- "@char: Two\n\n" # Invalid tag
- "@:\n\n" # Invalid line
+ "@pov: One\n\n" # Valid
+ "@char: Two\n\n" # Invalid tag
+ "@:\n\n" # Invalid line
"% synopsis: Synopsis One.\n\n"
"Paragraph One.\n\n"
))
@@ -441,6 +444,7 @@ def testCoreIndex_ScanText(nwMinimal, dummyGUI):
# END Test testCoreIndex_ScanText
+
@pytest.mark.core
def testCoreIndex_ExtractData(nwMinimal, dummyGUI):
"""Check the index data extraction functions.
@@ -499,9 +503,9 @@ def testCoreIndex_ExtractData(nwMinimal, dummyGUI):
# The novel file should have the correct counts
cC, wC, pC = theIndex.getCounts(nHandle)
- assert cC == 62 # Characters in text and title only
- assert wC == 12 # Words in text and title only
- assert pC == 2 # Paragraphs in text only
+ assert cC == 62 # Characters in text and title only
+ assert wC == 12 # Words in text and title only
+ assert pC == 2 # Paragraphs in text only
# getReferences
# =============
@@ -673,6 +677,7 @@ def testCoreIndex_ExtractData(nwMinimal, dummyGUI):
# END Test testCoreIndex_ExtractData
+
@pytest.mark.core
def testCoreIndex_CheckTagIndex(dummyGUI):
"""Test the tag index checker.
@@ -737,6 +742,7 @@ def testCoreIndex_CheckTagIndex(dummyGUI):
# END Test testCoreIndex_CheckTagIndex
+
@pytest.mark.core
def testCoreIndex_CheckRefIndex(dummyGUI):
"""Test the reference index checker.
@@ -859,6 +865,7 @@ def testCoreIndex_CheckRefIndex(dummyGUI):
# END Test testCoreIndex_CheckRefIndex
+
@pytest.mark.core
def testCoreIndex_CheckNovelNoteIndex(dummyGUI):
"""Test the novel and note index checkers.
@@ -1117,6 +1124,7 @@ def testCoreIndex_CheckNovelNoteIndex(dummyGUI):
# END Test testCoreIndex_CheckNovelNoteIndex
+
@pytest.mark.core
def testCoreIndex_CheckTextCounts(dummyGUI):
"""Test the text counts checker.
@@ -1173,6 +1181,7 @@ def testCoreIndex_CheckTextCounts(dummyGUI):
# END Test testCoreIndex_CheckTextCounts
+
@pytest.mark.core
def testCoreIndex_CountWords():
"""Test the word counter and the exclusion filers.
diff --git a/tests/test_core/test_core_item.py b/tests/test_core/test_core_item.py
index c93140fe..9f9a2432 100644
--- a/tests/test_core/test_core_item.py
+++ b/tests/test_core/test_core_item.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – NWItem Class Tester
=================================
@@ -28,6 +27,7 @@ from nw.core import NWProject
from nw.core.item import NWItem
from nw.enum import nwItemClass, nwItemType, nwItemLayout
+
@pytest.mark.core
def testCoreItem_Setters(dummyGUI):
"""Test all the simple setters for the NWItem class.
@@ -165,6 +165,7 @@ def testCoreItem_Setters(dummyGUI):
# END Test testCoreItem_Setters
+
@pytest.mark.core
def testCoreItem_TypeSetter(dummyGUI):
"""Test the setter for all the nwItemType values for the NWItem
@@ -193,6 +194,7 @@ def testCoreItem_TypeSetter(dummyGUI):
# END Test testCoreItem_TypeSetter
+
@pytest.mark.core
def testCoreItem_ClassSetter(dummyGUI):
"""Test the setter for all the nwItemClass values for the NWItem
@@ -233,6 +235,7 @@ def testCoreItem_ClassSetter(dummyGUI):
# END Test testCoreItem_ClassSetter
+
@pytest.mark.core
def testCoreItem_LayoutSetter(dummyGUI):
"""Test the setter for all the nwItemLayout values for the NWItem
@@ -269,6 +272,7 @@ def testCoreItem_LayoutSetter(dummyGUI):
# END Test testCoreItem_LayoutSetter
+
@pytest.mark.core
def testCoreItem_XMLPackUnpack(dummyGUI, caplog):
"""Test packing and unpacking XML objects for the NWItem class.
@@ -368,16 +372,17 @@ def testCoreItem_XMLPackUnpack(dummyGUI, caplog):
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
# Errors
+ # ======
- ## Not an Item
+ # Not an Item
mockXml = etree.SubElement(nwXML, "stuff")
assert theItem.unpackXML(mockXml) is False
- ## Item without Handle
+ # Item without Handle
mockXml = etree.SubElement(nwXML, "item", attrib={"stuff": "nah"})
assert theItem.unpackXML(mockXml) is False
- ## Item with Invalid SubElement is Accepted w/Error
+ # Item with Invalid SubElement is Accepted w/Error
mockXml = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"})
xParam = etree.SubElement(mockXml, "invalid")
xParam.text = "stuff"
diff --git a/tests/test_core/test_core_options.py b/tests/test_core/test_core_options.py
index c1ef5209..d41ba293 100644
--- a/tests/test_core/test_core_options.py
+++ b/tests/test_core/test_core_options.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – OptionState Class Tester
======================================
@@ -30,6 +29,7 @@ from nw.core import NWProject
from nw.core.options import OptionState
from nw.constants import nwFiles
+
@pytest.mark.core
def testCoreOptions_LoadSave(monkeypatch, dummyGUI, tmpDir):
"""Test loading and saving from the OptionState class.
@@ -100,8 +100,9 @@ def testCoreOptions_LoadSave(monkeypatch, dummyGUI, tmpDir):
# END Test testCoreOptions_LoadSave
+
@pytest.mark.core
-def testCoreOptions_SetGet(monkeypatch, dummyGUI, tmpDir):
+def testCoreOptions_SetGet(dummyGUI):
"""Test setting and getting values from the OptionState class.
"""
theProject = NWProject(dummyGUI)
diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py
index 2f016b38..7bc6b612 100644
--- a/tests/test_core/test_core_project.py
+++ b/tests/test_core/test_core_project.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – NWProject Class Tester
====================================
@@ -35,8 +34,9 @@ from nw.enum import nwItemClass, nwItemType, nwItemLayout
from nw.common import formatTimeStamp
from nw.constants import nwFiles
+
@pytest.mark.core
-def testCoreProject_NewMinimal(fncDir, outDir, refDir, tmpDir, dummyGUI):
+def testCoreProject_NewMinimal(fncDir, outDir, refDir, dummyGUI):
"""Create a new project from a project wizard dictionary. With
default setting, creating a Minimal project.
"""
@@ -83,6 +83,7 @@ def testCoreProject_NewMinimal(fncDir, outDir, refDir, tmpDir, dummyGUI):
# END Test testCoreProject_NewMinimal
+
@pytest.mark.core
def testCoreProject_NewCustomA(fncDir, outDir, refDir, dummyGUI):
"""Create a new project from a project wizard dictionary.
@@ -124,6 +125,7 @@ def testCoreProject_NewCustomA(fncDir, outDir, refDir, dummyGUI):
# END Test testCoreProject_NewCustomA
+
@pytest.mark.core
def testCoreProject_NewCustomB(fncDir, outDir, refDir, dummyGUI):
"""Create a new project from a project wizard dictionary.
@@ -165,6 +167,7 @@ def testCoreProject_NewCustomB(fncDir, outDir, refDir, dummyGUI):
# END Test testCoreProject_NewCustomB
+
@pytest.mark.core
def testCoreProject_NewSampleA(fncDir, tmpConf, dummyGUI, tmpDir):
"""Check that we can create a new project can be created from the
@@ -213,6 +216,7 @@ def testCoreProject_NewSampleA(fncDir, tmpConf, dummyGUI, tmpDir):
# END Test testCoreProject_NewSampleA
+
@pytest.mark.core
def testCoreProject_NewSampleB(monkeypatch, fncDir, tmpConf, dummyGUI, tmpDir):
"""Check that we can create a new project can be created from the
@@ -250,6 +254,7 @@ def testCoreProject_NewSampleB(monkeypatch, fncDir, tmpConf, dummyGUI, tmpDir):
# END Test testCoreProject_NewSampleB
+
@pytest.mark.core
def testCoreProject_NewRoot(fncDir, outDir, refDir, dummyGUI):
"""Check that new root folders can be added to the project.
@@ -286,6 +291,7 @@ def testCoreProject_NewRoot(fncDir, outDir, refDir, dummyGUI):
# END Test testCoreProject_NewRoot
+
@pytest.mark.core
def testCoreProject_NewFile(fncDir, outDir, refDir, dummyGUI):
"""Check that new files can be added to the project.
@@ -315,6 +321,7 @@ def testCoreProject_NewFile(fncDir, outDir, refDir, dummyGUI):
# END Test testCoreProject_NewFile
+
@pytest.mark.core
def testCoreProject_Open(monkeypatch, nwMinimal, dummyGUI):
"""Test opening a project.
@@ -436,6 +443,7 @@ def testCoreProject_Open(monkeypatch, nwMinimal, dummyGUI):
# END Test testCoreProject_Open
+
@pytest.mark.core
def testCoreProject_Save(monkeypatch, nwMinimal, dummyGUI, refDir):
"""Test saving a project.
@@ -481,6 +489,7 @@ def testCoreProject_Save(monkeypatch, nwMinimal, dummyGUI, refDir):
# END Test testCoreProject_Save
+
@pytest.mark.core
def testCoreProject_LockFile(monkeypatch, fncDir, dummyGUI):
"""Test lock file functions for the project folder.
@@ -540,6 +549,7 @@ def testCoreProject_LockFile(monkeypatch, fncDir, dummyGUI):
# END Test testCoreProject_LockFile
+
@pytest.mark.core
def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI):
"""Test helper functions for the project folder.
@@ -554,7 +564,7 @@ def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI):
# Block user's home folder
with monkeypatch.context() as mp:
- mp.setattr("os.path.expanduser", lambda *args, **kwargs: fncDir)
+ mp.setattr("os.path.expanduser", lambda *a, **k: fncDir)
assert theProject.ensureFolderStructure() is False
# Create a file to block meta folder
@@ -583,6 +593,7 @@ def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI):
# END Test testCoreProject_Helpers
+
@pytest.mark.core
def testCoreProject_AccessItems(nwMinimal, dummyGUI):
"""Test helper functions for the project folder.
@@ -592,24 +603,24 @@ def testCoreProject_AccessItems(nwMinimal, dummyGUI):
# Move Novel ROOT to after its files
oldOrder = [
- "a508bb932959c", # ROOT: Novel
- "a35baf2e93843", # FILE: Title Page
- "a6d311a93600a", # FOLDER: New Chapter
- "f5ab3e30151e1", # FILE: New Chapter
- "8c659a11cd429", # FILE: New Scene
- "7695ce551d265", # ROOT: Plot
- "afb3043c7b2b3", # ROOT: Characters
- "9d5247ab588e0", # ROOT: World
+ "a508bb932959c", # ROOT: Novel
+ "a35baf2e93843", # FILE: Title Page
+ "a6d311a93600a", # FOLDER: New Chapter
+ "f5ab3e30151e1", # FILE: New Chapter
+ "8c659a11cd429", # FILE: New Scene
+ "7695ce551d265", # ROOT: Plot
+ "afb3043c7b2b3", # ROOT: Characters
+ "9d5247ab588e0", # ROOT: World
]
newOrder = [
- "a35baf2e93843", # FILE: Title Page
- "f5ab3e30151e1", # FILE: New Chapter
- "8c659a11cd429", # FILE: New Scene
- "a6d311a93600a", # FOLDER: New Chapter
- "a508bb932959c", # ROOT: Novel
- "7695ce551d265", # ROOT: Plot
- "afb3043c7b2b3", # ROOT: Characters
- "9d5247ab588e0", # ROOT: World
+ "a35baf2e93843", # FILE: Title Page
+ "f5ab3e30151e1", # FILE: New Chapter
+ "8c659a11cd429", # FILE: New Scene
+ "a6d311a93600a", # FOLDER: New Chapter
+ "a508bb932959c", # ROOT: Novel
+ "7695ce551d265", # ROOT: Plot
+ "afb3043c7b2b3", # ROOT: Characters
+ "9d5247ab588e0", # ROOT: World
]
assert theProject.projTree.handles() == oldOrder
assert theProject.setTreeOrder(newOrder)
@@ -628,20 +639,21 @@ def testCoreProject_AccessItems(nwMinimal, dummyGUI):
retOrder.append(tItem.itemHandle)
assert retOrder == [
- "a508bb932959c", # ROOT: Novel
- "7695ce551d265", # ROOT: Plot
- "afb3043c7b2b3", # ROOT: Characters
- "9d5247ab588e0", # ROOT: World
- nHandle, # FILE: Test File
- "a35baf2e93843", # FILE: Title Page
- "a6d311a93600a", # FOLDER: New Chapter
- "f5ab3e30151e1", # FILE: New Chapter
- "8c659a11cd429", # FILE: New Scene
+ "a508bb932959c", # ROOT: Novel
+ "7695ce551d265", # ROOT: Plot
+ "afb3043c7b2b3", # ROOT: Characters
+ "9d5247ab588e0", # ROOT: World
+ nHandle, # FILE: Test File
+ "a35baf2e93843", # FILE: Title Page
+ "a6d311a93600a", # FOLDER: New Chapter
+ "f5ab3e30151e1", # FILE: New Chapter
+ "8c659a11cd429", # FILE: New Scene
]
assert theProject.projTree[nHandle].itemParent is None
# END Test testCoreProject_AccessItems
+
@pytest.mark.core
def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
"""Test other project class methods and functions.
@@ -789,10 +801,10 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
theProject.projTree["8c659a11cd429"].setStatus("Finished")
newList = [
("New", 1, 1, 1, "New"),
- ("Draft", 2, 2, 2, "Note"), # These are swapped
- ("Note", 3, 3, 3, "Draft"), # These are swapped
- ("Edited", 4, 4, 4, "Finished"), # Renamed
- ("Finished", 5, 5, 5, None), # New, with reused name
+ ("Draft", 2, 2, 2, "Note"), # These are swapped
+ ("Note", 3, 3, 3, "Draft"), # These are swapped
+ ("Edited", 4, 4, 4, "Finished"), # Renamed
+ ("Finished", 5, 5, 5, None), # New, with reused name
]
assert theProject.setStatusColours(newList)
assert theProject.statusItems._theLabels == [
@@ -801,10 +813,10 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
assert theProject.statusItems._theColours == [
(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5)
]
- assert theProject.projTree["a35baf2e93843"].itemStatus == "Edited" # Renamed
- assert theProject.projTree["a6d311a93600a"].itemStatus == "Note" # Swapped
- assert theProject.projTree["f5ab3e30151e1"].itemStatus == "Draft" # Swapped
- assert theProject.projTree["8c659a11cd429"].itemStatus == "Edited" # Renamed
+ assert theProject.projTree["a35baf2e93843"].itemStatus == "Edited" # Renamed
+ assert theProject.projTree["a6d311a93600a"].itemStatus == "Note" # Swapped
+ assert theProject.projTree["f5ab3e30151e1"].itemStatus == "Draft" # Swapped
+ assert theProject.projTree["8c659a11cd429"].itemStatus == "Edited" # Renamed
# Change importance
fHandle = theProject.newFile("Jane Doe", nwItemClass.CHARACTER, "afb3043c7b2b3")
@@ -839,7 +851,7 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
# Session stats
with monkeypatch.context() as mp:
- mp.setattr("os.path.isdir", lambda *args, **kwargs: False)
+ mp.setattr("os.path.isdir", lambda *a, **k: False)
assert not theProject._appendSessionStats(idleTime=0)
# Block open
@@ -892,6 +904,7 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
# END Test testCoreProject_Methods
+
@pytest.mark.core
def testCoreProject_OrphanedFiles(dummyGUI, nwLipsum):
"""Check that files in the content folder that are not tracked in
@@ -968,6 +981,7 @@ def testCoreProject_OrphanedFiles(dummyGUI, nwLipsum):
# END Test testCoreProject_OrphanedFiles
+
@pytest.mark.core
def testCoreProject_OldFormat(dummyGUI, nwOldProj):
"""Test that a project folder structure of version 1.0 can be
@@ -1057,6 +1071,7 @@ def testCoreProject_OldFormat(dummyGUI, nwOldProj):
# END Test testCoreProject_OldFormat
+
@pytest.mark.core
def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir):
"""Test the functins that handle legacy data folders and structure
@@ -1162,6 +1177,7 @@ def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir):
# END Test testCoreProject_LegacyData
+
@pytest.mark.core
def testCoreProject_Backup(monkeypatch, dummyGUI, nwMinimal, tmpDir):
"""Test the automated backup feature of the project class. The test
diff --git a/tests/test_core/test_core_spell.py b/tests/test_core/test_core_spell.py
index 4c3f3527..ec6ab23e 100644
--- a/tests/test_core/test_core_spell.py
+++ b/tests/test_core/test_core_spell.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Spell Check Classes Tester
========================================
@@ -29,6 +28,7 @@ from tools import readFile, writeFile
from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple
+
@pytest.mark.core
def testCoreSpell_Super(monkeypatch, tmpDir):
"""Test the spell checker super class
@@ -70,6 +70,7 @@ def testCoreSpell_Super(monkeypatch, tmpDir):
# END Test testCoreSpell_Super
+
@pytest.mark.core
def testCoreSpell_Enchant(monkeypatch, tmpDir):
"""Test the pyenchant spell checker
@@ -114,6 +115,7 @@ def testCoreSpell_Enchant(monkeypatch, tmpDir):
# END Test testCoreSpell_Enchant
+
@pytest.mark.core
def testCoreSpell_Simple(monkeypatch, tmpDir):
"""Test the fallback simple spell checker
diff --git a/tests/test_core/test_core_status.py b/tests/test_core/test_core_status.py
index d3cd7f86..8d145f10 100644
--- a/tests/test_core/test_core_status.py
+++ b/tests/test_core/test_core_status.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – NWStatus Class Tester
===================================
@@ -26,6 +25,7 @@ from lxml import etree
from nw.core.status import NWStatus
+
@pytest.mark.core
def testCoreStatus_Entries():
"""Test all the simple setters for the NWItem class.
@@ -100,6 +100,7 @@ def testCoreStatus_Entries():
# END Test testCoreStatus_Entries
+
@pytest.mark.core
def testCoreStatus_XMLPackUnpack():
"""Test all the simple setters for the NWItem class.
diff --git a/tests/test_core/test_core_tohtml.py b/tests/test_core/test_core_tohtml.py
index 8706c0c9..947ed3f0 100644
--- a/tests/test_core/test_core_tohtml.py
+++ b/tests/test_core/test_core_tohtml.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – ToHtml Class Tester
=================================
@@ -27,6 +26,7 @@ from tools import readFile
from nw.core import NWProject, NWIndex, ToHtml
+
@pytest.mark.core
def testCoreToHtml_Format(dummyGUI):
"""Test all the formatters for the ToHtml class.
@@ -79,6 +79,7 @@ def testCoreToHtml_Format(dummyGUI):
# END Test testCoreToHtml_Format
+
@pytest.mark.core
def testCoreToHtml_Convert(dummyGUI):
"""Test the converter of the ToHtml class.
@@ -344,6 +345,8 @@ def testCoreToHtml_Convert(dummyGUI):
# END Test testCoreToHtml_Convert
+
+@pytest.mark.core
def testCoreToHtml_Complex(dummyGUI, fncDir):
"""Test the ave method of the ToHtml class.
"""
@@ -416,6 +419,7 @@ def testCoreToHtml_Complex(dummyGUI, fncDir):
# END Test testCoreToHtml_Save
+
@pytest.mark.core
def testCoreToHtml_Methods(dummyGUI):
"""Test all the other methods of the ToHtml class.
diff --git a/tests/test_core/test_core_tokenizer.py b/tests/test_core/test_core_tokenizer.py
index 79a18b79..5202edb2 100644
--- a/tests/test_core/test_core_tokenizer.py
+++ b/tests/test_core/test_core_tokenizer.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Tokenizer Class Tester
====================================
@@ -28,6 +27,7 @@ from tools import readFile
from nw.core import NWProject, NWDoc
from nw.core.tokenizer import Tokenizer
+
@pytest.mark.core
def testCoreToken_Setters(dummyGUI):
"""Test all the setters for the Tokenizer class.
@@ -111,6 +111,7 @@ def testCoreToken_Setters(dummyGUI):
# END Test testCoreToken_Setters
+
@pytest.mark.core
def testCoreToken_TextOps(monkeypatch, nwMinimal, dummyGUI):
"""Test handling files and text in the Tokenizer class.
@@ -193,6 +194,7 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, dummyGUI):
# END Test testCoreToken_TextOps
+
@pytest.mark.core
def testCoreToken_Tokenize(dummyGUI):
"""Test the tokenization of the Tokenizer class.
@@ -494,6 +496,7 @@ def testCoreToken_Tokenize(dummyGUI):
# END Test testCoreToken_Tokenize
+
@pytest.mark.core
def testCoreToken_Headers(dummyGUI):
"""Test the header and page parser of the Tokenizer class.
diff --git a/tests/test_core/test_core_toodt.py b/tests/test_core/test_core_toodt.py
index 4aacf491..0221c8b4 100644
--- a/tests/test_core/test_core_toodt.py
+++ b/tests/test_core/test_core_toodt.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – ToOdt Class Tester
=================================
@@ -35,6 +34,7 @@ XML_NS = [
' xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"',
]
+
def xmlToText(xElem):
"""Get the text content of an XML element.
"""
@@ -43,6 +43,7 @@ def xmlToText(xElem):
rTxt = rTxt.replace(nSpace, "")
return rTxt
+
@pytest.mark.core
def testCoreToOdt_Convert(dummyGUI):
"""Test the converter of the ToHtml class.
diff --git a/tests/test_core/test_core_tree.py b/tests/test_core/test_core_tree.py
index 28a886d8..6be08c31 100644
--- a/tests/test_core/test_core_tree.py
+++ b/tests/test_core/test_core_tree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – NWTree Class Tester
=================================
@@ -30,6 +29,7 @@ from nw.core.project import NWProject, NWItem, NWTree
from nw.enum import nwItemClass, nwItemType, nwItemLayout
from nw.constants import nwFiles
+
@pytest.fixture(scope="function")
def dummyItems(dummyGUI):
"""Create a list of mock items.
@@ -106,6 +106,7 @@ def dummyItems(dummyGUI):
return theItems
+
@pytest.mark.core
def testCoreTree_BuildTree(dummyGUI, dummyItems):
"""Test building a project tree from a list of items.
@@ -202,6 +203,7 @@ def testCoreTree_BuildTree(dummyGUI, dummyItems):
# END Test testCoreTree_BuildTree
+
@pytest.mark.core
def testCoreTree_Methods(dummyGUI, dummyItems):
"""Test bvarious class methods.
@@ -258,6 +260,7 @@ def testCoreTree_Methods(dummyGUI, dummyItems):
# END Test testCoreTree_Methods
+
@pytest.mark.core
def testCoreTree_UpdateItemLayout(dummyGUI, dummyItems):
"""Test building a project tree from a list of items.
@@ -271,9 +274,9 @@ def testCoreTree_UpdateItemLayout(dummyGUI, dummyItems):
assert len(theTree) == len(dummyItems)
# Check rejected items
- assert not theTree.updateItemLayout("0000000000000", "H1") # Non-existent handle
- assert not theTree.updateItemLayout("a000000000004", "H2") # Character file
- assert not theTree.updateItemLayout("c000000000002", "H0") # Wrong header level
+ assert not theTree.updateItemLayout("0000000000000", "H1") # Non-existent handle
+ assert not theTree.updateItemLayout("a000000000004", "H2") # Character file
+ assert not theTree.updateItemLayout("c000000000002", "H0") # Wrong header level
cHandle = "c000000000002"
@@ -383,6 +386,7 @@ def testCoreTree_UpdateItemLayout(dummyGUI, dummyItems):
# END Test testCoreTree_UpdateItemLayout
+
@pytest.mark.core
def testCoreTree_MakeHandles(monkeypatch, dummyGUI):
"""Test generating item handles.
@@ -425,6 +429,7 @@ def testCoreTree_MakeHandles(monkeypatch, dummyGUI):
# END Test testCoreTree_MakeHandles
+
@pytest.mark.core
def testCoreTree_Stats(dummyGUI, dummyItems):
"""Test project stats methods.
@@ -451,6 +456,7 @@ def testCoreTree_Stats(dummyGUI, dummyItems):
# END Test testCoreTree_Stats
+
@pytest.mark.core
def testCoreTree_Reorder(dummyGUI, dummyItems):
"""Test changing tree order.
@@ -482,6 +488,7 @@ def testCoreTree_Reorder(dummyGUI, dummyItems):
# END Test testCoreTree_Reorder
+
@pytest.mark.core
def testCoreTree_XMLPackUnpack(dummyGUI, dummyItems):
"""Test packing and unpacking the tree to and from XML.
@@ -537,6 +544,7 @@ def testCoreTree_XMLPackUnpack(dummyGUI, dummyItems):
# END Test testCoreTree_XMLPackUnpack
+
@pytest.mark.core
def testCoreTree_ToCFile(monkeypatch, dummyGUI, dummyItems, tmpDir):
"""Test writing the ToC.txt file.
diff --git a/tests/test_dialogs/test_dlg_about.py b/tests/test_dialogs/test_dlg_about.py
index d951e81a..bf2c18af 100644
--- a/tests/test_dialogs/test_dlg_about.py
+++ b/tests/test_dialogs/test_dlg_about.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – About Dialog Class Tester
=======================================
@@ -32,12 +31,13 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testDlgAbout_Dialog(qtbot, monkeypatch, nwGUI):
"""Test the full about dialogs.
"""
# NW About
- monkeypatch.setattr(GuiAbout, "exec_", lambda *args: None)
+ monkeypatch.setattr(GuiAbout, "exec_", lambda *a: None)
nwGUI.mainMenu.aAboutNW.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiAbout") is not None, timeout=1000)
@@ -61,7 +61,7 @@ def testDlgAbout_Dialog(qtbot, monkeypatch, nwGUI):
assert msgAbout.tabBox.currentWidget() == msgAbout.pageNotes
# Qt About
- monkeypatch.setattr(QMessageBox, "aboutQt", lambda *args, **kwargs: None)
+ monkeypatch.setattr(QMessageBox, "aboutQt", lambda *a, **k: None)
nwGUI.mainMenu.aAboutQt.activate(QAction.Trigger)
# qtbot.stopForInteraction()
diff --git a/tests/test_dialogs/test_dlg_dialogs.py b/tests/test_dialogs/test_dlg_dialogs.py
index a60be95f..1d8033b0 100644
--- a/tests/test_dialogs/test_dlg_dialogs.py
+++ b/tests/test_dialogs/test_dlg_dialogs.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Other Dialog Classes Tester
=========================================
@@ -31,12 +30,13 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
-def testDlgOther_QuoteSelect(qtbot, monkeypatch, nwGUI, nwMinimal):
+def testDlgOther_QuoteSelect(monkeypatch, nwGUI):
"""Test the quote symbols dialog.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
nwQuot = GuiQuoteSelect(nwGUI)
nwQuot.show()
diff --git a/tests/test_dialogs/test_dlg_itemeditor.py b/tests/test_dialogs/test_dlg_itemeditor.py
index 9a9e6d66..2a61444c 100644
--- a/tests/test_dialogs/test_dlg_itemeditor.py
+++ b/tests/test_dialogs/test_dlg_itemeditor.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Item Editor Dialog Class Tester
=============================================
@@ -36,8 +35,9 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
-def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir, outDir):
+def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir):
"""Test the full item editor dialog.
"""
projFile = os.path.join(fncProj, "nwProject.nwx")
@@ -45,8 +45,8 @@ def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir,
compFile = os.path.join(refDir, "guiItemEditor_Dialog_nwProject.nwx")
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
# Create new, save, open project
nwGUI.theProject.projTree.setSeed(42)
@@ -54,7 +54,7 @@ def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir,
assert nwGUI.openDocument("0e17daca5f3e1")
assert nwGUI.treeView.setSelectedHandle("0e17daca5f3e1", doScroll=True)
- monkeypatch.setattr(GuiItemEditor, "exec_", lambda *args: None)
+ monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: None)
nwGUI.mainMenu.aEditItem.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000)
diff --git a/tests/test_dialogs/test_dlg_merge.py b/tests/test_dialogs/test_dlg_merge.py
index 52e8e892..5bcf6906 100644
--- a/tests/test_dialogs/test_dlg_merge.py
+++ b/tests/test_dialogs/test_dlg_merge.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Merge and Split Dialog Classes Tester
===================================================
@@ -36,8 +35,9 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
-def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
+def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj):
"""Test the merge documents tool.
"""
# Block message box
diff --git a/tests/test_dialogs/test_dlg_preferences.py b/tests/test_dialogs/test_dlg_preferences.py
index 1847dae2..2e89f63c 100644
--- a/tests/test_dialogs/test_dlg_preferences.py
+++ b/tests/test_dialogs/test_dlg_preferences.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Preferences Dialog Class Tester
=============================================
@@ -40,13 +39,14 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
"""Test the load project wizard.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
# Must create a clean config and GUI object as the test-wide
# nw.CONFIG object is created on import an can be tainted by other tests
@@ -69,8 +69,8 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
assert theConf.confPath == fncDir
theConf.spellTool = nwConst.SP_INTERNAL
- monkeypatch.setattr(GuiPreferences, "exec_", lambda *args: None)
- monkeypatch.setattr(GuiPreferences, "result", lambda *args: QDialog.Accepted)
+ monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
+ monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
nwGUI.mainMenu.aPreferences.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000)
@@ -125,9 +125,9 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
# qtbot.stopForInteraction()
# Check Browse button
- monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "")
+ monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "")
assert not tabProjects._backupFolder()
- monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "some/dir")
+ monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "some/dir")
qtbot.mouseClick(tabProjects.backupGetPath, Qt.LeftButton)
qtbot.wait(keyDelay)
diff --git a/tests/test_dialogs/test_dlg_projload.py b/tests/test_dialogs/test_dlg_projload.py
index d552cc88..0dcc6d79 100644
--- a/tests/test_dialogs/test_dlg_projload.py
+++ b/tests/test_dialogs/test_dlg_projload.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Load Dialog Class Tester
==============================================
@@ -37,6 +36,7 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
"""Test the load project wizard.
@@ -48,8 +48,8 @@ def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
assert nwGUI.closeProject()
qtbot.wait(stepDelay)
- monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *args: None)
- monkeypatch.setattr(GuiProjectLoad, "result", lambda *args: QDialog.Accepted)
+ monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *a: None)
+ monkeypatch.setattr(GuiProjectLoad, "result", lambda *a: QDialog.Accepted)
nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000)
@@ -106,7 +106,7 @@ def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
getFile = os.path.join(nwMinimal, "nwProject.nwx")
- monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwargs: (getFile, None))
+ monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *a, **k: (getFile, None))
qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton)
assert nwLoad.openPath == nwMinimal
assert nwLoad.openState == nwLoad.OPEN_STATE
diff --git a/tests/test_dialogs/test_dlg_projsettings.py b/tests/test_dialogs/test_dlg_projsettings.py
index b753959e..acdfad21 100644
--- a/tests/test_dialogs/test_dlg_projsettings.py
+++ b/tests/test_dialogs/test_dlg_projsettings.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Settings Dialog Class Tester
==================================================
@@ -38,6 +37,7 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDir, refDir):
"""Test the full project settings dialog.
@@ -47,8 +47,8 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi
compFile = os.path.join(refDir, "guiProjSettings_Dialog_nwProject.nwx")
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
# Check that we cannot open when there is no project
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
@@ -64,8 +64,8 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi
nwGUI.theProject.setAutoReplace({"A": "B", "C": "D"})
# Get the dialog object
- monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *args: None)
- monkeypatch.setattr(GuiProjectSettings, "result", lambda *args: QDialog.Accepted)
+ monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *a: None)
+ monkeypatch.setattr(GuiProjectSettings, "result", lambda *a: QDialog.Accepted)
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000)
@@ -135,7 +135,7 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi
assert projEdit.tabStatus.listBox.topLevelItemCount() == 3
# Add a new item
- monkeypatch.setattr(QColorDialog, "getColor", lambda *args: QColor(20, 30, 40))
+ monkeypatch.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
qtbot.mouseClick(projEdit.tabStatus.addButton, Qt.LeftButton)
projEdit.tabStatus.listBox.topLevelItem(3).setSelected(True)
for n in range(8):
diff --git a/tests/test_dialogs/test_dlg_split.py b/tests/test_dialogs/test_dlg_split.py
index 87d2f837..1c761615 100644
--- a/tests/test_dialogs/test_dlg_split.py
+++ b/tests/test_dialogs/test_dlg_split.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Merge and Split Dialog Classes Tester
===================================================
@@ -37,8 +36,9 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
-def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
+def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj):
"""Test the split document tool.
"""
# Block message box
diff --git a/tests/test_dialogs/test_dlg_wordlist.py b/tests/test_dialogs/test_dlg_wordlist.py
index 31cfb9e0..c854f073 100644
--- a/tests/test_dialogs/test_dlg_wordlist.py
+++ b/tests/test_dialogs/test_dlg_wordlist.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Other Dialog Classes Tester
=========================================
@@ -21,6 +20,7 @@ along with this program. If not, see .
"""
import os
+import pytest
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QMessageBox, QAction
@@ -35,14 +35,16 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
-def testDlgWordList_Dialog(qtbot, monkeypatch, nwGUI, nwMinimal, tmpDir):
+
+@pytest.mark.gui
+def testDlgWordList_Dialog(qtbot, monkeypatch, nwGUI, nwMinimal):
"""test the word list editor.
"""
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(GuiWordList, "exec_", lambda *args: None)
- monkeypatch.setattr(GuiWordList, "result", lambda *args: QDialog.Accepted)
- monkeypatch.setattr(GuiWordList, "accept", lambda *args: None)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(GuiWordList, "exec_", lambda *a: None)
+ monkeypatch.setattr(GuiWordList, "result", lambda *a: QDialog.Accepted)
+ monkeypatch.setattr(GuiWordList, "accept", lambda *a: None)
# Open project
nwGUI.openProject(nwMinimal)
@@ -66,7 +68,7 @@ def testDlgWordList_Dialog(qtbot, monkeypatch, nwGUI, nwMinimal, tmpDir):
"word_a\n"
"word_c\n"
"word_g\n"
- " \n" # Should be ignored
+ " \n" # Should be ignored
"word_f\n"
"word_b\n"
))
diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py
index af28535c..aee859a3 100644
--- a/tests/test_gui/test_gui_doceditor.py
+++ b/tests/test_gui/test_gui_doceditor.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Main GUI Editor Class Tester
==========================================
@@ -20,8 +19,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import pytest
import os
+import pytest
from shutil import copyfile
from tools import cmpFiles
@@ -39,17 +38,18 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir):
"""Test the document editor.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(GuiItemEditor, "exec_", lambda *args: None)
- monkeypatch.setattr(GuiItemEditor, "result", lambda *args: QDialog.Accepted)
- monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True)
- monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *args: True)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: None)
+ monkeypatch.setattr(GuiItemEditor, "result", lambda *a: QDialog.Accepted)
+ monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
+ monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True)
# Create new, save, close project
nwGUI.theProject.projTree.setSeed(42)
@@ -315,7 +315,7 @@ def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir):
assert nwGUI.treeView.deleteItem()
assert nwGUI.treeView.setSelectedHandle(newHandle)
assert nwGUI.treeView.deleteItem()
- assert nwGUI.theProject.projTree["2fca346db6561"] is not None # Trash
+ assert nwGUI.theProject.projTree["2fca346db6561"] is not None # Trash
assert nwGUI.saveProject()
# Check the files
@@ -353,13 +353,14 @@ def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir):
# END Test testGuiEditor_Main
+
@pytest.mark.gui
def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the document editor search functionality.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *args: True)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True)
nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.openProject(nwLipsum)
@@ -414,7 +415,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
# Set Invalid RegEx
assert nwGUI.docEditor.docSearch.setSearchText(r"\bSus[")
qtbot.mouseClick(nwGUI.docEditor.docSearch.searchButton, Qt.LeftButton, delay=keyDelay)
- assert nwGUI.docEditor.getCursorPosition() < 3 # No result
+ assert nwGUI.docEditor.getCursorPosition() < 3 # No result
# Set Valid RegEx
assert nwGUI.docEditor.docSearch.setSearchText(r"\bSus")
@@ -503,7 +504,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
# Next Match
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
- assert nwGUI.docEditor.docHandle() == "2426c6f0ca922" # Next document
+ assert nwGUI.docEditor.docHandle() == "2426c6f0ca922" # Next document
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 620) < 3
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
diff --git a/tests/test_gui/test_gui_docviewer.py b/tests/test_gui/test_gui_docviewer.py
index 8af6ccbc..98276853 100644
--- a/tests/test_gui/test_gui_docviewer.py
+++ b/tests/test_gui/test_gui_docviewer.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Main GUI Viewer Class Tester
==========================================
@@ -32,13 +31,14 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the document viewer.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
# Open project
nwGUI.theProject.projTree.setSeed(42)
diff --git a/tests/test_gui/test_gui_mainmenu.py b/tests/test_gui/test_gui_mainmenu.py
index 752e596e..9eacb197 100644
--- a/tests/test_gui/test_gui_mainmenu.py
+++ b/tests/test_gui/test_gui_mainmenu.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Main GUI Main Menu Class Tester
=============================================
@@ -35,6 +34,7 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the main menu Edit and Format entries.
@@ -113,44 +113,45 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
qtbot.wait(stepDelay)
# Block Formats
+ # =============
assert nwGUI.docEditor.setCursorPosition(30)
- ## Header 1
+ # Header 1
nwGUI.mainMenu.aFmtHead1.activate(QAction.Trigger)
fmtStr = "# Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:76] == fmtStr
qtbot.wait(stepDelay)
- ## Header 2
+ # Header 2
nwGUI.mainMenu.aFmtHead2.activate(QAction.Trigger)
fmtStr = "## Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:77] == fmtStr
qtbot.wait(stepDelay)
- ## Header 3
+ # Header 3
nwGUI.mainMenu.aFmtHead3.activate(QAction.Trigger)
fmtStr = "### Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:78] == fmtStr
qtbot.wait(stepDelay)
- ## Header 4
+ # Header 4
nwGUI.mainMenu.aFmtHead4.activate(QAction.Trigger)
fmtStr = "#### Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:79] == fmtStr
qtbot.wait(stepDelay)
- ## Clear Format
+ # Clear Format
nwGUI.mainMenu.aFmtNoFormat.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[27:74] == cleanText
qtbot.wait(stepDelay)
- ## Comment On
+ # Comment On
nwGUI.mainMenu.aFmtComment.activate(QAction.Trigger)
fmtStr = "% Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:76] == fmtStr
qtbot.wait(stepDelay)
- ## Comment Off
+ # Comment Off
nwGUI.mainMenu.aFmtComment.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[27:74] == cleanText
qtbot.wait(stepDelay)
@@ -228,41 +229,43 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
assert nwGUI.docEditor.isEmpty()
# Alignment & Indent
+ # ==================
+
cleanText = "A single, short paragraph.\n\n"
nwGUI.docEditor.setText(cleanText)
assert nwGUI.docEditor.setCursorPosition(0)
- ## Left Align
+ # Left Align
nwGUI.mainMenu.aFmtAlignLeft.activate(QAction.Trigger)
fmtStr = "A single, short paragraph. <<"
assert nwGUI.docEditor.getText()[:29] == fmtStr
qtbot.wait(stepDelay)
- ## Right Align
+ # Right Align
nwGUI.mainMenu.aFmtAlignRight.activate(QAction.Trigger)
fmtStr = ">> A single, short paragraph."
assert nwGUI.docEditor.getText()[:29] == fmtStr
qtbot.wait(stepDelay)
- ## Centre Align
+ # Centre Align
nwGUI.mainMenu.aFmtAlignCentre.activate(QAction.Trigger)
fmtStr = ">> A single, short paragraph. <<"
assert nwGUI.docEditor.getText()[:32] == fmtStr
qtbot.wait(stepDelay)
- ## Left Indent
+ # Left Indent
nwGUI.mainMenu.aFmtIndentLeft.activate(QAction.Trigger)
fmtStr = "> A single, short paragraph."
assert nwGUI.docEditor.getText()[:28] == fmtStr
qtbot.wait(stepDelay)
- ## Right Indent
+ # Right Indent
nwGUI.mainMenu.aFmtIndentRight.activate(QAction.Trigger)
fmtStr = "> A single, short paragraph. <"
assert nwGUI.docEditor.getText()[:30] == fmtStr
qtbot.wait(stepDelay)
- ## No Format
+ # No Format
nwGUI.mainMenu.aFmtNoFormat.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[:30] == cleanText
qtbot.wait(stepDelay)
@@ -368,6 +371,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
# END Test testGuiMenu_EditFormat
+
@pytest.mark.gui
def testGuiMenu_ContextMenus(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the context menus.
@@ -452,6 +456,7 @@ def testGuiMenu_ContextMenus(qtbot, monkeypatch, nwGUI, nwLipsum):
# END Test testGuiMenu_ContextMenus
+
@pytest.mark.gui
def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
"""Test the Insert menu.
diff --git a/tests/test_gui/test_gui_noveltree.py b/tests/test_gui/test_gui_noveltree.py
index 57f83fe5..aae675d8 100644
--- a/tests/test_gui/test_gui_noveltree.py
+++ b/tests/test_gui/test_gui_noveltree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Main GUI Novel Tree Class Tester
==============================================
@@ -28,13 +27,14 @@ from tools import writeFile
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMessageBox
+
@pytest.mark.gui
-def testGuiNovelTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
+def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
"""Test navigating the novel tree.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
nwGUI.openProject(nwMinimal)
nwGUI.theProject.projTree.setSeed(42)
diff --git a/tests/test_gui/test_gui_outline.py b/tests/test_gui/test_gui_outline.py
index 507ad410..83a9d57f 100644
--- a/tests/test_gui/test_gui_outline.py
+++ b/tests/test_gui/test_gui_outline.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Main GUI Outline Class Tester
===========================================
@@ -31,13 +30,14 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the outline view.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
assert nwGUI.openProject(nwLipsum)
nwGUI.mainConf.lastPath = nwLipsum
diff --git a/tests/test_gui/test_gui_projdetails.py b/tests/test_gui/test_gui_projdetails.py
index e0ead1f9..ae20e613 100644
--- a/tests/test_gui/test_gui_projdetails.py
+++ b/tests/test_gui/test_gui_projdetails.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Project Details Dialog Class Tester
=================================================
@@ -32,15 +31,16 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testGuiProjDetails_Dialog(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the project details dialog.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
# Create a project to work on
assert nwGUI.openProject(nwLipsum)
diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py
index c595eaf1..f73de6d6 100644
--- a/tests/test_gui/test_gui_projtree.py
+++ b/tests/test_gui/test_gui_projtree.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Main GUI Project Tree Class Tester
================================================
@@ -32,16 +31,17 @@ from nw.guimain import GuiMain
from nw.gui.projtree import GuiProjectTree
from nw.enum import nwItemType, nwItemClass
+
@pytest.mark.gui
def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
"""Test adding and removing items from the project tree.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(GuiMain, "editItem", lambda *args: None)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(GuiMain, "editItem", lambda *a: None)
nwGUI.theProject.projTree.setSeed(42)
nwTree = nwGUI.treeView
@@ -82,8 +82,8 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
]
# Add roots
- assert not nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.WORLD) # Duplicate
- assert nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.CUSTOM) # Valid
+ assert not nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.WORLD) # Duplicate
+ assert nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.CUSTOM) # Valid
# Change max depth and try to add a subfolder that is too deep
monkeypatch.setattr("nw.constants.nwConst.MAX_DEPTH", 2)
@@ -98,12 +98,12 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
nwTree.setSelectedHandle("8c659a11cd429")
# Shift focus and try to move item
- monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: False)
+ monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: False)
assert not nwTree.moveTreeItem(1)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "44cb730c42048", "71ee45a3c0db9"
]
- monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True)
+ monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
# Move second item up twice (should give same result)
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
@@ -168,12 +168,12 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
# Delete the items we added earlier
nwTree.clearSelection()
- assert not nwTree.emptyTrash() # No folder yet
+ assert not nwTree.emptyTrash() # No folder yet
assert not nwTree.deleteItem(None)
assert not nwTree.deleteItem("1111111111111")
- assert nwTree.deleteItem("73475cb40a568") # New File
- assert nwTree.deleteItem("71ee45a3c0db9") # New Folder
- assert nwTree.deleteItem("811786ad1ae74") # Custom Root
+ assert nwTree.deleteItem("73475cb40a568") # New File
+ assert nwTree.deleteItem("71ee45a3c0db9") # New Folder
+ assert nwTree.deleteItem("811786ad1ae74") # Custom Root
assert "73475cb40a568" in nwGUI.theProject.projTree._treeOrder
assert "71ee45a3c0db9" not in nwGUI.theProject.projTree._treeOrder
assert "811786ad1ae74" not in nwGUI.theProject.projTree._treeOrder
@@ -181,7 +181,7 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
# The file is in trash, empty it
assert os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
assert nwTree.emptyTrash()
- assert not nwTree.emptyTrash() # Already empty
+ assert not nwTree.emptyTrash() # Already empty
assert not os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
assert "73475cb40a568" not in nwGUI.theProject.projTree._treeOrder
@@ -228,7 +228,7 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
nwTree.clearSelection()
# Add a file with no parent, and fail to find a suitable parent item
- monkeypatch.setattr("nw.core.tree.NWTree.findRoot", lambda *args: None)
+ monkeypatch.setattr("nw.core.tree.NWTree.findRoot", lambda *a: None)
assert not nwTree.newTreeItem(nwItemType.FILE, nwItemClass.NOVEL)
assert not nwTree.newTreeItem(nwItemType.FOLDER, nwItemClass.NOVEL)
diff --git a/tests/test_gui/test_gui_theme.py b/tests/test_gui/test_gui_theme.py
index cb9c993b..b9fc1f69 100644
--- a/tests/test_gui/test_gui_theme.py
+++ b/tests/test_gui/test_gui_theme.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – GUI Theme and Icons Classes Tester
================================================
@@ -30,12 +29,13 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir):
"""Test the theme and icon classes.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % tmpDir, nwMinimal])
qtbot.addWidget(nwGUI)
diff --git a/tests/test_tools/test_tools_build.py b/tests/test_tools/test_tools_build.py
index 46865368..f91625c7 100644
--- a/tests/test_tools/test_tools_build.py
+++ b/tests/test_tools/test_tools_build.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Build Dialog Class Tester
=======================================
@@ -35,14 +34,15 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
"""Test the build tool.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda a, b, c, **kwargs: (c, None))
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda a, b, c, **k: (c, None))
# Check that we cannot open when there is no project
nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger)
@@ -69,7 +69,7 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
# Non-existent path
with monkeypatch.context() as mp:
- mp.setattr("os.path.expanduser", lambda *args, **kwargs: nwLipsum)
+ mp.setattr("os.path.expanduser", lambda *a, **k: nwLipsum)
assert nwGUI.mainConf.lastPath != nwLipsum
nwGUI.mainConf.lastPath = "no_such_path"
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
@@ -77,7 +77,7 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
# No path selected
with monkeypatch.context() as mp:
- mp.setattr(QFileDialog, "getSaveFileName", lambda *args, **kwargs: ("", ""))
+ mp.setattr(QFileDialog, "getSaveFileName", lambda *a, **k: ("", ""))
assert not nwBuild._saveDocument(nwBuild.FMT_NWD)
# Default Settings
diff --git a/tests/test_tools/test_tools_projwizard.py b/tests/test_tools/test_tools_projwizard.py
index 52ab91ff..2e6a76d4 100644
--- a/tests/test_tools/test_tools_projwizard.py
+++ b/tests/test_tools/test_tools_projwizard.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – New Project Wizard Class Tester
=============================================
@@ -39,13 +38,14 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testToolProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
"""Test the new project wizard.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
if sys.platform.startswith("darwin"):
# Disable for macOS because the test segfaults on QWizard.show()
@@ -62,22 +62,22 @@ def testToolProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
# Close project, but call with invalid path
assert nwGUI.closeProject()
with monkeypatch.context() as mp:
- mp.setattr(nwGUI, "showNewProjectDialog", lambda *args: None)
+ mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: None)
assert not nwGUI.newProject()
# Now, with an empty dictionary
- mp.setattr(nwGUI, "showNewProjectDialog", lambda *args: {})
+ mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {})
assert not nwGUI.newProject()
# Now, with a non-empty folder
- mp.setattr(nwGUI, "showNewProjectDialog", lambda *args: {"projPath": nwMinimal})
+ mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {"projPath": nwMinimal})
assert not nwGUI.newProject()
##
# Test the Wizard
##
- monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *args: None)
+ monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *a: None)
nwGUI.mainConf.lastPath = " "
nwGUI.closeProject()
@@ -184,7 +184,7 @@ def testToolProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
# Final Page
finalPage = nwWiz.currentPage()
assert isinstance(finalPage, ProjWizardFinalPage)
- assert nwWiz.button(QWizard.FinishButton).isEnabled() # But we don't click it
+ assert nwWiz.button(QWizard.FinishButton).isEnabled() # But we don't click it
# Check Data
projData = nwGUI._assembleProjectWizardData(nwWiz)
diff --git a/tests/test_tools/test_tools_writingstats.py b/tests/test_tools/test_tools_writingstats.py
index 10f4fddc..995bc2fb 100644
--- a/tests/test_tools/test_tools_writingstats.py
+++ b/tests/test_tools/test_tools_writingstats.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Writing Stats Dialog Class Tester
===============================================
@@ -37,15 +36,16 @@ keyDelay = 2
typeDelay = 1
stepDelay = 20
+
@pytest.mark.gui
def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
"""Test the full writing stats tool.
"""
# Block message box
- monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes)
- monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
# Create a project to work on
assert nwGUI.newProject({"projPath": fncProj})
@@ -116,13 +116,13 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
sessLog.populateGUI()
# Make the saving fail
- monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda *args, **kwargs: ("", ""))
+ monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda *a, **k: ("", ""))
assert not sessLog._saveData(sessLog.FMT_CSV)
assert not sessLog._saveData(sessLog.FMT_JSON)
assert not sessLog._saveData(None)
# Make the save succeed
- monkeypatch.setattr("os.path.expanduser", lambda *args: fncDir)
+ monkeypatch.setattr("os.path.expanduser", lambda *a: fncDir)
monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda ss, tt, pp, options: (pp, ""))
sessLog.listBox.sortByColumn(sessLog.C_TIME, 0)
diff --git a/tests/tools.py b/tests/tools.py
index b375f671..6c8b2512 100644
--- a/tests/tools.py
+++ b/tests/tools.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
novelWriter – Test Suite Tools
==============================
@@ -25,6 +24,7 @@ import shutil
from PyQt5.QtWidgets import qApp
+
def cmpFiles(fileOne, fileTwo, ignoreLines=None):
"""Compare two files, but optionally ignore lines given by a list.
"""
@@ -70,6 +70,7 @@ def cmpFiles(fileOne, fileTwo, ignoreLines=None):
return not diffFound
+
def getGuiItem(theName):
"""Returns a QtWidget based on its objectName.
"""
@@ -78,18 +79,21 @@ def getGuiItem(theName):
return qWidget
return None
+
def readFile(fileName):
"""Returns the content of a file as a string.
"""
with open(fileName, mode="r", encoding="utf8") as inFile:
return inFile.read()
+
def writeFile(fileName, fileData):
"""Write the contents of a string to a file.
"""
with open(fileName, mode="w", encoding="utf8") as outFile:
outFile.write(fileData)
+
def cleanProject(projPath):
"""Delete all generated files in a project.
"""