Merge pull request #816 from vkbo/style

Style
This commit is contained in:
Veronica Berglyd Olsen
2021-06-25 21:56:03 +02:00
committed by GitHub
93 changed files with 986 additions and 725 deletions
+2 -2
View File
@@ -25,5 +25,5 @@ jobs:
flake8 tests --count --select=E9,F63,F7,F82 --show-source --statistics flake8 tests --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Coding Style Violations - name: Coding Style Violations
run: | run: |
flake8 nw --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,E261,E266,E302,E305 --show-source --statistics flake8 tests --count --max-line-length=99 --ignore E203,E221,E226,E228,E241,E251 --show-source --statistics
+14 -27
View File
@@ -77,28 +77,28 @@ The `setup.cfg` file in the root of this project has the following settings for
matches the coding standard: matches the coding standard:
```conf ```conf
[flake8] [flake8]
ignore = E203,E221,E226,E228,E241,E251,E261,E266,E302,E305 ignore = E203,E221,E226,E228,E241,E251
max-line-length = 99 max-line-length = 99
exclude = docs/* exclude = docs/*
``` ```
The command line equivalent, with reporting, is: The command line equivalent, with reporting, is:
```bash ```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 Passing this check is required before contributions are merged into the `main`, `testing` or `dev`
checked automatically when you make a pull request. You can run the `flake8` command locally to branches. This is checked automatically when you make a pull request. You can run the `flake8`
check beforehand. The full command will give you a detailed description of the code lines that do command locally to check beforehand. The full command will give you a detailed description of the
not conform to the standard. code lines that do not conform to the standard.
## Ignored Errors ## Ignored Errors
Some `flake8` error codes are ignored for this project for various reasons. The source also uses 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 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 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 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. 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. **Reason:** Column alignment.
**E226:** missing whitespace around arithmetic operator **E226:** missing whitespace around arithmetic operator
**Reason:** This doesn't actually follow the PEP8 recommendation of grouping longer equations by **Reason:** This doesn't actually follow the
operator precedence like `2*a + 3*b` instead of `a * a + 3 * b`. Generally, don't use spaces around [PEP8 recommendation](https://www.python.org/dev/peps/pep-0008/#other-recommendations)
`*`, `/` and `**`, but _do_ use spaces around `+` and `-`. For appending strings, the spaces can be of grouping longer equations by operator precedence like `2*a + 3*b` instead of `a * a + 3 * b`.
dropped. Don't use the `+` operator for appending multiple strings. Use formatting instead. 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 **E228** missing whitespace around modulo operator
**Reason:** See reason for E226. Formatting `%` like `/` and `*` should be possible. **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 **E251:** unexpected spaces around keyword / parameter equals
**Reason:** Column alignment. **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.
-1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# #
# Configuration file for the Sphinx documentation builder. # Configuration file for the Sphinx documentation builder.
# #
-1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
Qt Base Translation File Qt Base Translation File
======================== ========================
-1
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" """
novelWriter Start Script novelWriter Start Script
========================== ==========================
+5 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Init File novelWriter Init File
======================= =======================
@@ -90,15 +89,19 @@ __docurl__ = "https://novelwriter.readthedocs.io"
# Add verbose logging level # Add verbose logging level
VERBOSE = 5 VERBOSE = 5
logging.addLevelName(VERBOSE, "VERBOSE") logging.addLevelName(VERBOSE, "VERBOSE")
def logVerbose(self, message, *args, **kws): def logVerbose(self, message, *args, **kws):
if self.isEnabledFor(VERBOSE): if self.isEnabledFor(VERBOSE):
self._log(VERBOSE, message, args, **kws) self._log(VERBOSE, message, args, **kws)
logging.Logger.verbose = logVerbose logging.Logger.verbose = logVerbose
# Initiating logging # Initiating logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
## ##
# Main Program # Main Program
## ##
@@ -106,6 +109,7 @@ logger = logging.getLogger(__name__)
# Load the main config as a global object # Load the main config as a global object
CONFIG = Config() CONFIG = Config()
def main(sysArgs=None): def main(sysArgs=None):
"""Parses command line, sets up logging, and launches main GUI. """Parses command line, sets up logging, and launches main GUI.
""" """
+19 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Common Functions novelWriter Common Functions
============================== ==============================
@@ -36,6 +35,7 @@ from nw.constants import nwConst, nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def checkString(value, default, allowNone=False): def checkString(value, default, allowNone=False):
"""Check if a variable is a string or a none. """Check if a variable is a string or a none.
""" """
@@ -48,6 +48,7 @@ def checkString(value, default, allowNone=False):
return str(value) return str(value)
return default return default
def checkInt(value, default, allowNone=False): def checkInt(value, default, allowNone=False):
"""Check if a variable is an integer or a none. """Check if a variable is an integer or a none.
""" """
@@ -61,6 +62,7 @@ def checkInt(value, default, allowNone=False):
except Exception: except Exception:
return default return default
def checkBool(value, default, allowNone=False): def checkBool(value, default, allowNone=False):
"""Check if a variable is a boolean or a none. """Check if a variable is a boolean or a none.
""" """
@@ -85,6 +87,7 @@ def checkBool(value, default, allowNone=False):
return default return default
return default return default
def checkHandle(value, default, allowNone=False): def checkHandle(value, default, allowNone=False):
"""Check if a value is a handle. """Check if a value is a handle.
""" """
@@ -97,6 +100,7 @@ def checkHandle(value, default, allowNone=False):
return str(value) return str(value)
return default return default
def isHandle(theString): def isHandle(theString):
"""Check if a string is a valid novelWriter handle. """Check if a string is a valid novelWriter handle.
Note: This is case sensitive. Must be lower case! Note: This is case sensitive. Must be lower case!
@@ -110,6 +114,7 @@ def isHandle(theString):
return False return False
return True return True
def isTitleTag(theString): def isTitleTag(theString):
"""Check if a string is a valid title string. """Check if a string is a valid title string.
""" """
@@ -124,21 +129,25 @@ def isTitleTag(theString):
return False return False
return True return True
def isItemClass(theString): def isItemClass(theString):
"""Check if an item is a calid nwItemClass identifier. """Check if an item is a calid nwItemClass identifier.
""" """
return theString in nwItemClass.__members__ return theString in nwItemClass.__members__
def isItemType(theString): def isItemType(theString):
"""Check if an item is a calid nwItemType identifier. """Check if an item is a calid nwItemType identifier.
""" """
return theString in nwItemType.__members__ return theString in nwItemType.__members__
def isItemLayout(theString): def isItemLayout(theString):
"""Check if an item is a calid nwItemLayout identifier. """Check if an item is a calid nwItemLayout identifier.
""" """
return theString in nwItemLayout.__members__ return theString in nwItemLayout.__members__
def hexToInt(value, default=0): def hexToInt(value, default=0):
"""Convert a hex string to an integer. """Convert a hex string to an integer.
""" """
@@ -149,6 +158,7 @@ def hexToInt(value, default=0):
return default return default
return default return default
def formatInt(theInt): def formatInt(theInt):
"""Formats an integer with k, M, G etc. """Formats an integer with k, M, G etc.
""" """
@@ -168,6 +178,7 @@ def formatInt(theInt):
return str(theInt) return str(theInt)
def formatTimeStamp(theTime, fileSafe=False): def formatTimeStamp(theTime, fileSafe=False):
"""Take a number (on the format returned by time.time()) and convert """Take a number (on the format returned by time.time()) and convert
it to a timestamp string. it to a timestamp string.
@@ -177,6 +188,7 @@ def formatTimeStamp(theTime, fileSafe=False):
else: else:
return datetime.fromtimestamp(theTime).strftime(nwConst.FMT_TSTAMP) return datetime.fromtimestamp(theTime).strftime(nwConst.FMT_TSTAMP)
def formatTime(tS): def formatTime(tS):
"""Format a time in seconds in HH:MM:SS format or d-HH:MM:SS format """Format a time in seconds in HH:MM:SS format or d-HH:MM:SS format
if a full day or longer. 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 f"{tS//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}"
return "ERROR" return "ERROR"
def splitVersionNumber(vString): def splitVersionNumber(vString):
""" Splits a version string on the form aa.bb.cc into major, minor """ Splits a version string on the form aa.bb.cc into major, minor
and patch, and computes an integer value aabbcc. and patch, and computes an integer value aabbcc.
@@ -211,6 +224,7 @@ def splitVersionNumber(vString):
return [vMajor, vMinor, vPatch, vInt] return [vMajor, vMinor, vPatch, vInt]
def transferCase(theSource, theTarget): def transferCase(theSource, theTarget):
"""Transfers the case of the source word to the target word. This """Transfers the case of the source word to the target word. This
will consider all upper or lower, and first char capitalisation. will consider all upper or lower, and first char capitalisation.
@@ -232,6 +246,7 @@ def transferCase(theSource, theTarget):
return theResult return theResult
def fuzzyTime(secDiff): def fuzzyTime(secDiff):
"""Converts a time difference in seconds into a fuzzy time string. """Converts a time difference in seconds into a fuzzy time string.
""" """
@@ -292,6 +307,7 @@ def fuzzyTime(secDiff):
"Common", "{0} years ago" "Common", "{0} years ago"
).format(int(round(secDiff/31557600))) ).format(int(round(secDiff/31557600)))
def makeFileNameSafe(theText): def makeFileNameSafe(theText):
"""Returns a filename safe version of the text. """Returns a filename safe version of the text.
""" """
@@ -301,6 +317,7 @@ def makeFileNameSafe(theText):
cleanName += c cleanName += c
return cleanName return cleanName
def getGuiItem(theName): def getGuiItem(theName):
"""Returns a QtWidget based on its objectName. """Returns a QtWidget based on its objectName.
""" """
@@ -309,6 +326,7 @@ def getGuiItem(theName):
return qWidget return qWidget
return None return None
def numberToRoman(numVal, isLower=False): def numberToRoman(numVal, isLower=False):
"""Convert an integer to a roman number. """Convert an integer to a roman number.
""" """
+26 -26
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Config Class novelWriter Config Class
========================== ==========================
@@ -45,6 +44,7 @@ from nw.constants import nwConst, nwFiles, nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Config: class Config:
CNF_STR = 0 CNF_STR = 0
@@ -85,7 +85,7 @@ class Config:
self.confChanged = False # True whenever the config has chenged, false after save 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.hasHelp = False # True if the Qt help files are present in the assets folder
## General # General
self.guiTheme = "default" self.guiTheme = "default"
self.guiSyntax = "default_light" self.guiSyntax = "default_light"
self.guiIcons = "typicons_colour_light" self.guiIcons = "typicons_colour_light"
@@ -95,14 +95,14 @@ class Config:
self.guiScale = 1.0 # Set automatically by Theme class self.guiScale = 1.0 # Set automatically by Theme class
self.lastNotes = "0x0" # The latest release notes that have been shown self.lastNotes = "0x0" # The latest release notes that have been shown
## Localisation # Localisation
self.qLocal = QLocale.system() self.qLocal = QLocale.system()
self.guiLang = self.qLocal.name() self.guiLang = self.qLocal.name()
self.qtLangPath = QLibraryInfo.location(QLibraryInfo.TranslationsPath) self.qtLangPath = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
self.nwLangPath = None self.nwLangPath = None
self.qtTrans = {} self.qtTrans = {}
## Sizes # Sizes
self.winGeometry = [1200, 650] self.winGeometry = [1200, 650]
self.prefGeometry = [700, 615] self.prefGeometry = [700, 615]
self.treeColWidth = [200, 50, 30] self.treeColWidth = [200, 50, 30]
@@ -114,15 +114,15 @@ class Config:
self.outlnPanePos = [500, 150] self.outlnPanePos = [500, 150]
self.isFullScreen = False self.isFullScreen = False
## Features # Features
self.hideVScroll = False # Hide vertical scroll bars on main widgets self.hideVScroll = False # Hide vertical scroll bars on main widgets
self.hideHScroll = False # Hide horizontal scroll bars on main widgets self.hideHScroll = False # Hide horizontal scroll bars on main widgets
## Project # Project
self.autoSaveProj = 60 # Interval for auto-saving project in seconds self.autoSaveProj = 60 # Interval for auto-saving project in seconds
self.autoSaveDoc = 30 # Interval for auto-saving document in seconds self.autoSaveDoc = 30 # Interval for auto-saving document in seconds
## Text Editor # Text Editor
self.textFont = None # Editor font self.textFont = None # Editor font
self.textSize = 12 # Editor font size self.textSize = 12 # Editor font size
self.textFixedW = True # Keep editor text fixed width self.textFixedW = True # Keep editor text fixed width
@@ -161,7 +161,7 @@ class Config:
self.stopWhenIdle = True # Stop the status bar clock when the user is idle self.stopWhenIdle = True # Stop the status bar clock when the user is idle
self.userIdleTime = 300 # Time of inactivity to consider user idle self.userIdleTime = 300 # Time of inactivity to consider user idle
## User-Selected Symbols # User-Selected Symbols
self.fmtApostrophe = nwUnicode.U_RSQUO self.fmtApostrophe = nwUnicode.U_RSQUO
self.fmtSingleQuotes = [nwUnicode.U_LSQUO, nwUnicode.U_RSQUO] self.fmtSingleQuotes = [nwUnicode.U_LSQUO, nwUnicode.U_RSQUO]
self.fmtDoubleQuotes = [nwUnicode.U_LDQUO, nwUnicode.U_RDQUO] self.fmtDoubleQuotes = [nwUnicode.U_LDQUO, nwUnicode.U_RDQUO]
@@ -169,11 +169,11 @@ class Config:
self.fmtPadAfter = "" self.fmtPadAfter = ""
self.fmtPadThin = False self.fmtPadThin = False
## Spell Checking # Spell Checking
self.spellTool = None self.spellTool = None
self.spellLanguage = None self.spellLanguage = None
## Search Bar Switches # Search Bar Switches
self.searchCase = False self.searchCase = False
self.searchWord = False self.searchWord = False
self.searchRegEx = False self.searchRegEx = False
@@ -181,12 +181,12 @@ class Config:
self.searchNextFile = False self.searchNextFile = False
self.searchMatchCap = False self.searchMatchCap = False
## Backup # Backup
self.backupPath = "" self.backupPath = ""
self.backupOnClose = False self.backupOnClose = False
self.askBeforeBackup = True self.askBeforeBackup = True
## State # State
self.showRefPanel = True self.showRefPanel = True
self.viewComments = True self.viewComments = True
self.viewSynopsis = True self.viewSynopsis = True
@@ -445,7 +445,7 @@ class Config:
self.errData.append(str(e)) self.errData.append(str(e))
return False return False
## Main # Main
cnfSec = "Main" cnfSec = "Main"
self.guiTheme = self._parseLine( self.guiTheme = self._parseLine(
cnfParse, cnfSec, "theme", self.CNF_STR, self.guiTheme cnfParse, cnfSec, "theme", self.CNF_STR, self.guiTheme
@@ -472,7 +472,7 @@ class Config:
cnfParse, cnfSec, "guilang", self.CNF_STR, self.guiLang cnfParse, cnfSec, "guilang", self.CNF_STR, self.guiLang
) )
## Sizes # Sizes
cnfSec = "Sizes" cnfSec = "Sizes"
self.winGeometry = self._parseLine( self.winGeometry = self._parseLine(
cnfParse, cnfSec, "geometry", self.CNF_I_LST, self.winGeometry cnfParse, cnfSec, "geometry", self.CNF_I_LST, self.winGeometry
@@ -511,7 +511,7 @@ class Config:
cnfParse, cnfSec, "hidehscroll", self.CNF_BOOL, self.hideHScroll cnfParse, cnfSec, "hidehscroll", self.CNF_BOOL, self.hideHScroll
) )
## Project # Project
cnfSec = "Project" cnfSec = "Project"
self.autoSaveProj = self._parseLine( self.autoSaveProj = self._parseLine(
cnfParse, cnfSec, "autosaveproject", self.CNF_INT, self.autoSaveProj cnfParse, cnfSec, "autosaveproject", self.CNF_INT, self.autoSaveProj
@@ -520,7 +520,7 @@ class Config:
cnfParse, cnfSec, "autosavedoc", self.CNF_INT, self.autoSaveDoc cnfParse, cnfSec, "autosavedoc", self.CNF_INT, self.autoSaveDoc
) )
## Editor # Editor
cnfSec = "Editor" cnfSec = "Editor"
self.textFont = self._parseLine( self.textFont = self._parseLine(
cnfParse, cnfSec, "textfont", self.CNF_STR, self.textFont cnfParse, cnfSec, "textfont", self.CNF_STR, self.textFont
@@ -631,7 +631,7 @@ class Config:
cnfParse, cnfSec, "useridletime", self.CNF_INT, self.userIdleTime cnfParse, cnfSec, "useridletime", self.CNF_INT, self.userIdleTime
) )
## Backup # Backup
cnfSec = "Backup" cnfSec = "Backup"
self.backupPath = self._parseLine( self.backupPath = self._parseLine(
cnfParse, cnfSec, "backuppath", self.CNF_STR, self.backupPath cnfParse, cnfSec, "backuppath", self.CNF_STR, self.backupPath
@@ -643,7 +643,7 @@ class Config:
cnfParse, cnfSec, "askbeforebackup", self.CNF_BOOL, self.askBeforeBackup cnfParse, cnfSec, "askbeforebackup", self.CNF_BOOL, self.askBeforeBackup
) )
## State # State
cnfSec = "State" cnfSec = "State"
self.showRefPanel = self._parseLine( self.showRefPanel = self._parseLine(
cnfParse, cnfSec, "showrefpanel", self.CNF_BOOL, self.showRefPanel cnfParse, cnfSec, "showrefpanel", self.CNF_BOOL, self.showRefPanel
@@ -673,7 +673,7 @@ class Config:
cnfParse, cnfSec, "searchmatchcap", self.CNF_BOOL, self.searchMatchCap cnfParse, cnfSec, "searchmatchcap", self.CNF_BOOL, self.searchMatchCap
) )
## Path # Path
cnfSec = "Path" cnfSec = "Path"
self.lastPath = self._parseLine( self.lastPath = self._parseLine(
cnfParse, cnfSec, "lastpath", self.CNF_STR, self.lastPath cnfParse, cnfSec, "lastpath", self.CNF_STR, self.lastPath
@@ -704,7 +704,7 @@ class Config:
# Set options # Set options
## Main # Main
cnfSec = "Main" cnfSec = "Main"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "timestamp", formatTimeStamp(time())) cnfParse.set(cnfSec, "timestamp", formatTimeStamp(time()))
@@ -717,7 +717,7 @@ class Config:
cnfParse.set(cnfSec, "lastnotes", str(self.lastNotes)) cnfParse.set(cnfSec, "lastnotes", str(self.lastNotes))
cnfParse.set(cnfSec, "guilang", str(self.guiLang)) cnfParse.set(cnfSec, "guilang", str(self.guiLang))
## Sizes # Sizes
cnfSec = "Sizes" cnfSec = "Sizes"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "geometry", self._packList(self.winGeometry)) cnfParse.set(cnfSec, "geometry", self._packList(self.winGeometry))
@@ -733,13 +733,13 @@ class Config:
cnfParse.set(cnfSec, "hidevscroll", str(self.hideVScroll)) cnfParse.set(cnfSec, "hidevscroll", str(self.hideVScroll))
cnfParse.set(cnfSec, "hidehscroll", str(self.hideHScroll)) cnfParse.set(cnfSec, "hidehscroll", str(self.hideHScroll))
## Project # Project
cnfSec = "Project" cnfSec = "Project"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "autosaveproject", str(self.autoSaveProj)) cnfParse.set(cnfSec, "autosaveproject", str(self.autoSaveProj))
cnfParse.set(cnfSec, "autosavedoc", str(self.autoSaveDoc)) cnfParse.set(cnfSec, "autosavedoc", str(self.autoSaveDoc))
## Editor # Editor
cnfSec = "Editor" cnfSec = "Editor"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "textfont", str(self.textFont)) cnfParse.set(cnfSec, "textfont", str(self.textFont))
@@ -779,14 +779,14 @@ class Config:
cnfParse.set(cnfSec, "stopwhenidle", str(self.stopWhenIdle)) cnfParse.set(cnfSec, "stopwhenidle", str(self.stopWhenIdle))
cnfParse.set(cnfSec, "useridletime", str(self.userIdleTime)) cnfParse.set(cnfSec, "useridletime", str(self.userIdleTime))
## Backup # Backup
cnfSec = "Backup" cnfSec = "Backup"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "backuppath", str(self.backupPath)) cnfParse.set(cnfSec, "backuppath", str(self.backupPath))
cnfParse.set(cnfSec, "backuponclose", str(self.backupOnClose)) cnfParse.set(cnfSec, "backuponclose", str(self.backupOnClose))
cnfParse.set(cnfSec, "askbeforebackup", str(self.askBeforeBackup)) cnfParse.set(cnfSec, "askbeforebackup", str(self.askBeforeBackup))
## State # State
cnfSec = "State" cnfSec = "State"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "showrefpanel", str(self.showRefPanel)) cnfParse.set(cnfSec, "showrefpanel", str(self.showRefPanel))
@@ -799,7 +799,7 @@ class Config:
cnfParse.set(cnfSec, "searchnextfile", str(self.searchNextFile)) cnfParse.set(cnfSec, "searchnextfile", str(self.searchNextFile))
cnfParse.set(cnfSec, "searchmatchcap", str(self.searchMatchCap)) cnfParse.set(cnfSec, "searchmatchcap", str(self.searchMatchCap))
## Path # Path
cnfSec = "Path" cnfSec = "Path"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec, "lastpath", str(self.lastPath)) cnfParse.set(cnfSec, "lastpath", str(self.lastPath))
+24 -15
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Constants novelWriter Constants
======================= =======================
@@ -28,11 +27,13 @@ from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP
from nw.enum import nwItemClass, nwItemLayout, nwItemType, nwOutline from nw.enum import nwItemClass, nwItemLayout, nwItemType, nwOutline
def trConst(tString): def trConst(tString):
"""Wrapper function for locally translating constants. """Wrapper function for locally translating constants.
""" """
return QCoreApplication.translate("Constant", tString) return QCoreApplication.translate("Constant", tString)
class nwConst(): class nwConst():
# Date and Time Formats # Date and Time Formats
@@ -51,6 +52,7 @@ class nwConst():
# END Class nwConst # END Class nwConst
class nwLists(): class nwLists():
"""Lists used for grouping various other constants. """Lists used for grouping various other constants.
""" """
@@ -65,6 +67,7 @@ class nwLists():
# END Class nwLists # END Class nwLists
class nwRegEx(): class nwRegEx():
FMT_EI = r"(?<![\w\\])(_)(?![\s_])(.+?)(?<![\s\\])(\1)(?!\w)" FMT_EI = r"(?<![\w\\])(_)(?![\s_])(.+?)(?<![\s\\])(\1)(?!\w)"
@@ -73,6 +76,7 @@ class nwRegEx():
# END Class nwRegEx # END Class nwRegEx
class nwFiles(): class nwFiles():
PROJ_FILE = "nwProject.nwx" PROJ_FILE = "nwProject.nwx"
@@ -87,6 +91,7 @@ class nwFiles():
# END Class nwFiles # END Class nwFiles
class nwKeyWords: class nwKeyWords:
TAG_KEY = "@tag" TAG_KEY = "@tag"
@@ -121,6 +126,7 @@ class nwKeyWords:
# END Class nwKeyWords # END Class nwKeyWords
class nwLabels(): class nwLabels():
CLASS_NAME = { CLASS_NAME = {
@@ -218,6 +224,7 @@ class nwLabels():
# END Class nwLabels # END Class nwLabels
class nwQuotes(): class nwQuotes():
"""Allowed quotation marks. """Allowed quotation marks.
Source: https://en.wikipedia.org/wiki/Quotation_mark Source: https://en.wikipedia.org/wiki/Quotation_mark
@@ -249,13 +256,14 @@ class nwQuotes():
# END Class nwQuotes # END Class nwQuotes
class nwUnicode: class nwUnicode:
"""Supported unicode character constants and their HTML equivalents. """Supported unicode character constants and their HTML equivalents.
""" """
# Unicode Constants # Unicode Constants
# ================= # =================
## Quotation Marks # Quotation Marks
U_QUOT = "\u0022" # Quotation mark U_QUOT = "\u0022" # Quotation mark
U_APOS = "\u0027" # Apostrophe U_APOS = "\u0027" # Apostrophe
U_LAQUO = "\u00ab" # Left-pointing double angle quotation mark U_LAQUO = "\u00ab" # Left-pointing double angle quotation mark
@@ -276,7 +284,7 @@ class nwUnicode:
U_LWCQUO = "\u300e" # Left white corner bracket U_LWCQUO = "\u300e" # Left white corner bracket
U_RWCQUO = "\u300f" # Right white corner bracket U_RWCQUO = "\u300f" # Right white corner bracket
## Punctuation # Punctuation
U_FGDASH = "\u2012" # Figure dash U_FGDASH = "\u2012" # Figure dash
U_ENDASH = "\u2013" # Short dash U_ENDASH = "\u2013" # Short dash
U_EMDASH = "\u2014" # Long dash U_EMDASH = "\u2014" # Long dash
@@ -286,7 +294,7 @@ class nwUnicode:
U_PRIME = "\u2032" # Prime U_PRIME = "\u2032" # Prime
U_DPRIME = "\u2033" # Double prime U_DPRIME = "\u2033" # Double prime
## Spaces and Lines # Spaces and Lines
U_NBSP = "\u00a0" # Non-breaking space U_NBSP = "\u00a0" # Non-breaking space
U_THSP = "\u2009" # Thin space U_THSP = "\u2009" # Thin space
U_THNBSP = "\u202f" # Thin non-breaking space U_THNBSP = "\u202f" # Thin non-breaking space
@@ -295,7 +303,7 @@ class nwUnicode:
U_LSEP = "\u2028" # Line separator U_LSEP = "\u2028" # Line separator
U_PSEP = "\u2029" # Paragraph separator U_PSEP = "\u2029" # Paragraph separator
## Symbols # Symbols
U_CHECK = "\u2714" # Heavy check mark U_CHECK = "\u2714" # Heavy check mark
U_CROSS = "\u2715" # Heavy cross mark U_CROSS = "\u2715" # Heavy cross mark
U_BULL = "\u2022" # List bullet U_BULL = "\u2022" # List bullet
@@ -308,7 +316,7 @@ class nwUnicode:
U_TIMES = "\u00d7" # Multiplaction sign U_TIMES = "\u00d7" # Multiplaction sign
U_DIVIDE = "\u00f7" # Division sign U_DIVIDE = "\u00f7" # Division sign
## Arrows # Arrows
U_UTRI = "\u25b2" # Up-pointing triangle U_UTRI = "\u25b2" # Up-pointing triangle
U_UTRIS = "\u25b4" # Up-pointing triangle, small U_UTRIS = "\u25b4" # Up-pointing triangle, small
U_RTRI = "\u25b6" # Right-pointing triangle U_RTRI = "\u25b6" # Right-pointing triangle
@@ -321,7 +329,7 @@ class nwUnicode:
# HTML Equivalents # HTML Equivalents
# ================ # ================
## Quotes # Quotes
H_QUOT = "&quot;" H_QUOT = "&quot;"
H_APOS = "&#39;" H_APOS = "&#39;"
H_LAQUO = "&laquo;" H_LAQUO = "&laquo;"
@@ -342,7 +350,7 @@ class nwUnicode:
H_LWCQUO = "&#12302;" H_LWCQUO = "&#12302;"
H_RWCQUO = "&#12303;" H_RWCQUO = "&#12303;"
## Punctuation # Punctuation
H_FGDASH = "&#8210;" H_FGDASH = "&#8210;"
H_ENDASH = "&ndash;" H_ENDASH = "&ndash;"
H_EMDASH = "&mdash;" H_EMDASH = "&mdash;"
@@ -352,14 +360,14 @@ class nwUnicode:
H_PRIME = "&prime;" H_PRIME = "&prime;"
H_DPRIME = "&#8243;" H_DPRIME = "&#8243;"
## Spaces # Spaces
H_NBSP = "&nbsp;" H_NBSP = "&nbsp;"
H_THSP = "&thinsp;" H_THSP = "&thinsp;"
H_THNBSP = "&#8239;" H_THNBSP = "&#8239;"
H_ENSP = "&ensp;" H_ENSP = "&ensp;"
H_EMSP = "&emsp;" H_EMSP = "&emsp;"
## Symbols # Symbols
H_CHECK = "&#10004;" H_CHECK = "&#10004;"
H_CROSS = "&#10005;" H_CROSS = "&#10005;"
H_BULL = "&bull;" H_BULL = "&bull;"
@@ -372,7 +380,7 @@ class nwUnicode:
H_TIMES = "&times;" H_TIMES = "&times;"
H_DIVIDE = "&divide;" H_DIVIDE = "&divide;"
## Arrows # Arrows
H_UTRI = "&#9650;" H_UTRI = "&#9650;"
H_UTRIS = "&#9652;" H_UTRIS = "&#9652;"
H_RTRI = "&#9654;" H_RTRI = "&#9654;"
@@ -384,10 +392,11 @@ class nwUnicode:
# END Class nwUnicode # END Class nwUnicode
class nwHtmlUnicode(): class nwHtmlUnicode():
U_TO_H = { U_TO_H = {
## Quotes # Quotes
nwUnicode.U_QUOT : nwUnicode.H_QUOT, nwUnicode.U_QUOT : nwUnicode.H_QUOT,
nwUnicode.U_APOS : nwUnicode.H_APOS, nwUnicode.U_APOS : nwUnicode.H_APOS,
nwUnicode.U_LAQUO : nwUnicode.H_LAQUO, nwUnicode.U_LAQUO : nwUnicode.H_LAQUO,
@@ -408,7 +417,7 @@ class nwHtmlUnicode():
nwUnicode.U_LWCQUO : nwUnicode.H_LWCQUO, nwUnicode.U_LWCQUO : nwUnicode.H_LWCQUO,
nwUnicode.U_RWCQUO : nwUnicode.H_RWCQUO, nwUnicode.U_RWCQUO : nwUnicode.H_RWCQUO,
## Punctuation # Punctuation
nwUnicode.U_FGDASH : nwUnicode.H_FGDASH, nwUnicode.U_FGDASH : nwUnicode.H_FGDASH,
nwUnicode.U_ENDASH : nwUnicode.H_ENDASH, nwUnicode.U_ENDASH : nwUnicode.H_ENDASH,
nwUnicode.U_EMDASH : nwUnicode.H_EMDASH, nwUnicode.U_EMDASH : nwUnicode.H_EMDASH,
@@ -418,14 +427,14 @@ class nwHtmlUnicode():
nwUnicode.U_PRIME : nwUnicode.H_PRIME, nwUnicode.U_PRIME : nwUnicode.H_PRIME,
nwUnicode.U_DPRIME : nwUnicode.H_DPRIME, nwUnicode.U_DPRIME : nwUnicode.H_DPRIME,
## Spaces # Spaces
nwUnicode.U_NBSP : nwUnicode.H_NBSP, nwUnicode.U_NBSP : nwUnicode.H_NBSP,
nwUnicode.U_THSP : nwUnicode.H_THSP, nwUnicode.U_THSP : nwUnicode.H_THSP,
nwUnicode.U_THNBSP : nwUnicode.H_THNBSP, nwUnicode.U_THNBSP : nwUnicode.H_THNBSP,
nwUnicode.U_ENSP : nwUnicode.H_ENSP, nwUnicode.U_ENSP : nwUnicode.H_ENSP,
nwUnicode.U_EMSP : nwUnicode.H_EMSP, nwUnicode.U_EMSP : nwUnicode.H_EMSP,
## Symbols # Symbols
nwUnicode.U_CHECK : nwUnicode.H_CHECK, nwUnicode.U_CHECK : nwUnicode.H_CHECK,
nwUnicode.U_CROSS : nwUnicode.H_CROSS, nwUnicode.U_CROSS : nwUnicode.H_CROSS,
nwUnicode.U_BULL : nwUnicode.H_BULL, nwUnicode.U_BULL : nwUnicode.H_BULL,
+20 -1
View File
@@ -1,4 +1,23 @@
# -*- coding: utf-8 -*- """
novelWriter Core Init
=======================
This file is a part of novelWriter
Copyright 20182021, 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 <https://www.gnu.org/licenses/>.
"""
from nw.core.document import NWDoc from nw.core.document import NWDoc
from nw.core.index import NWIndex, countWords from nw.core.index import NWIndex, countWords
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Document novelWriter Project Document
============================== ==============================
@@ -32,6 +31,7 @@ from nw.common import isHandle
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class NWDoc(): class NWDoc():
def __init__(self, theProject, theHandle): def __init__(self, theProject, theHandle):
+2 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Index novelWriter Project Index
=========================== ===========================
@@ -39,6 +38,7 @@ from nw.core.document import NWDoc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class NWIndex(): class NWIndex():
H_VALID = ("H0", "H1", "H2", "H3", "H4") H_VALID = ("H0", "H1", "H2", "H3", "H4")
@@ -895,6 +895,7 @@ class NWIndex():
# END Class NWIndex # END Class NWIndex
# =============================================================================================== # # =============================================================================================== #
# Simple Word Counter # Simple Word Counter
# =============================================================================================== # # =============================================================================================== #
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Item Class novelWriter Project Item Class
================================ ================================
@@ -33,6 +32,7 @@ from nw.common import checkInt, isHandle, isItemClass, isItemLayout, isItemType
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class NWItem(): class NWItem():
def __init__(self, theProject): def __init__(self, theProject):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Options Cache novelWriter Project Options Cache
=================================== ===================================
@@ -34,6 +33,7 @@ from nw.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class OptionState(): class OptionState():
def __init__(self, theProject): def __init__(self, theProject):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Wrapper novelWriter Project Wrapper
============================= =============================
@@ -50,6 +49,7 @@ from nw.constants import trConst, nwFiles, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class NWProject(): class NWProject():
def __init__(self, theParent): def __init__(self, theParent):
+4 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Spell Check Classes novelWriter Spell Check Classes
================================= =================================
@@ -31,6 +30,7 @@ import difflib
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# =============================================================================================== # # =============================================================================================== #
# SpellChecking SuperClass # SpellChecking SuperClass
# =============================================================================================== # # =============================================================================================== #
@@ -122,6 +122,7 @@ class NWSpellCheck():
# END Class NWSpellCheck # END Class NWSpellCheck
# =============================================================================================== # # =============================================================================================== #
# Enchant Based SpellChecking # Enchant Based SpellChecking
# =============================================================================================== # # =============================================================================================== #
@@ -208,6 +209,7 @@ class NWSpellEnchant(NWSpellCheck):
# END Class NWSpellEnchant # END Class NWSpellEnchant
class FakeEnchant: class FakeEnchant:
"""Fallback for when Enchant is selected, but not installed. """Fallback for when Enchant is selected, but not installed.
""" """
@@ -225,6 +227,7 @@ class FakeEnchant:
# END Class FakeEnchant # END Class FakeEnchant
# =============================================================================================== # # =============================================================================================== #
# Fallback SpellChecking Using difflib # Fallback SpellChecking Using difflib
# =============================================================================================== # # =============================================================================================== #
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Item Status Class novelWriter Project Item Status Class
======================================= =======================================
@@ -32,6 +31,7 @@ from nw.common import checkInt
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class NWStatus(): class NWStatus():
def __init__(self): def __init__(self):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter HTML Text Converter novelWriter HTML Text Converter
================================= =================================
@@ -31,6 +30,7 @@ from nw.constants import nwKeyWords, nwLabels, nwHtmlUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ToHtml(Tokenizer): class ToHtml(Tokenizer):
M_PREVIEW = 0 # Tweak output for the DocViewer M_PREVIEW = 0 # Tweak output for the DocViewer
+3 -3
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Text Tokenizer novelWriter Text Tokenizer
============================ ============================
@@ -40,6 +39,7 @@ from nw.core.document import NWDoc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Tokenizer(): class Tokenizer():
# In-Text Format # In-Text Format
@@ -107,7 +107,7 @@ class Tokenizer():
self.doComments = False # Also process comments self.doComments = False # Also process comments
self.doKeywords = False # Also process keywords like tags and references self.doKeywords = False # Also process keywords like tags and references
## Margins # Margins
self.marginTitle = (1.000, 0.500) self.marginTitle = (1.000, 0.500)
self.marginHead1 = (1.000, 0.500) self.marginHead1 = (1.000, 0.500)
self.marginHead2 = (0.834, 0.500) self.marginHead2 = (0.834, 0.500)
@@ -116,7 +116,7 @@ class Tokenizer():
self.marginText = (0.000, 0.584) self.marginText = (0.000, 0.584)
self.marginMeta = (0.000, 0.584) self.marginMeta = (0.000, 0.584)
## Title Formats # Title Formats
self.fmtTitle = "%title%" # Formatting for titles self.fmtTitle = "%title%" # Formatting for titles
self.fmtChapter = "%title%" # Formatting for numbered chapters self.fmtChapter = "%title%" # Formatting for numbered chapters
self.fmtUnNum = "%title%" # Formatting for unnumbered chapters self.fmtUnNum = "%title%" # Formatting for unnumbered chapters
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Markdown Text Converter novelWriter Markdown Text Converter
===================================== =====================================
@@ -31,6 +30,7 @@ from nw.core.tokenizer import Tokenizer
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ToMarkdown(Tokenizer): class ToMarkdown(Tokenizer):
M_STD = 0 # Standard Markdown M_STD = 0 # Standard Markdown
+7 -4
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter ODT Text Converter novelWriter ODT Text Converter
================================ ================================
@@ -57,6 +56,7 @@ TAG_TAB = "{%s}tab" % XML_NS["text"]
TAG_SPAN = "{%s}span" % XML_NS["text"] TAG_SPAN = "{%s}span" % XML_NS["text"]
TAG_STNM = "{%s}style-name" % XML_NS["text"] TAG_STNM = "{%s}style-name" % XML_NS["text"]
class ToOdt(Tokenizer): class ToOdt(Tokenizer):
X_BLD = 0x01 # Bold format X_BLD = 0x01 # Bold format
@@ -114,7 +114,7 @@ class ToOdt(Tokenizer):
self._dLanguage = "en" self._dLanguage = "en"
self._dCountry = "GB" self._dCountry = "GB"
## Text Margings in Units of em # Text Margings in Units of em
self._mTopTitle = "0.423cm" self._mTopTitle = "0.423cm"
self._mTopHead1 = "0.423cm" self._mTopHead1 = "0.423cm"
self._mTopHead2 = "0.353cm" self._mTopHead2 = "0.353cm"
@@ -133,13 +133,13 @@ class ToOdt(Tokenizer):
self._mBotText = "0.247cm" self._mBotText = "0.247cm"
self._mBotMeta = "0.106cm" self._mBotMeta = "0.106cm"
## Document Margins # Document Margins
self._mDocTop = "2.000cm" self._mDocTop = "2.000cm"
self._mDocBtm = "2.000cm" self._mDocBtm = "2.000cm"
self._mDocLeft = "2.000cm" self._mDocLeft = "2.000cm"
self._mDocRight = "2.000cm" self._mDocRight = "2.000cm"
## Colour # Colour
self._colHead12 = None self._colHead12 = None
self._opaHead12 = None self._opaHead12 = None
self._colHead34 = None self._colHead34 = None
@@ -985,6 +985,7 @@ class ToOdt(Tokenizer):
# END Class ToOdt # END Class ToOdt
# =============================================================================================== # # =============================================================================================== #
# Auto-Style Classes # Auto-Style Classes
# =============================================================================================== # # =============================================================================================== #
@@ -1212,6 +1213,7 @@ class ODTParagraphStyle():
# END Class ODTParagraphStyle # END Class ODTParagraphStyle
class ODTTextStyle(): class ODTTextStyle():
"""Wrapper class for the text style setting used by the exporter. """Wrapper class for the text style setting used by the exporter.
Only the used settings are exposed here to keep the class minimal Only the used settings are exposed here to keep the class minimal
@@ -1282,6 +1284,7 @@ class ODTTextStyle():
# END Class ODTTextStyle # END Class ODTTextStyle
# =============================================================================================== # # =============================================================================================== #
# Local Functions # Local Functions
# =============================================================================================== # # =============================================================================================== #
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Tree Class novelWriter Project Tree Class
================================ ================================
@@ -62,6 +61,7 @@ LAYOUT_MAP = {
}, },
} }
class NWTree(): class NWTree():
def __init__(self, theProject): def __init__(self, theProject):
+20 -1
View File
@@ -1,4 +1,23 @@
# -*- coding: utf-8 -*- """
novelWriter Dialogs Init
==========================
This file is a part of novelWriter
Copyright 20182021, 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 <https://www.gnu.org/licenses/>.
"""
from nw.dialogs.about import GuiAbout from nw.dialogs.about import GuiAbout
from nw.dialogs.docmerge import GuiDocMerge from nw.dialogs.docmerge import GuiDocMerge
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI About Box novelWriter GUI About Box
=========================== ===========================
@@ -39,6 +38,7 @@ from PyQt5.QtWidgets import (
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiAbout(QDialog): class GuiAbout(QDialog):
def __init__(self, theParent): def __init__(self, theParent):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Doc Merge Tool novelWriter GUI Doc Merge Tool
================================ ================================
@@ -39,6 +38,7 @@ from nw.gui.custom import QHelpLabel
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiDocMerge(QDialog): class GuiDocMerge(QDialog):
def __init__(self, theParent): def __init__(self, theParent):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Doc Split Tool novelWriter GUI Doc Split Tool
================================ ================================
@@ -40,6 +39,7 @@ from nw.gui.custom import QHelpLabel
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiDocSplit(QDialog): class GuiDocSplit(QDialog):
def __init__(self, theParent): def __init__(self, theParent):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Item Editor novelWriter GUI Item Editor
============================= =============================
@@ -39,6 +38,7 @@ from nw.gui.custom import QSwitch
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiItemEditor(QDialog): class GuiItemEditor(QDialog):
def __init__(self, theParent, tHandle): def __init__(self, theParent, tHandle):
+50 -43
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Preferences novelWriter GUI Preferences
============================= =============================
@@ -43,6 +42,7 @@ from nw.dialogs.quotes import GuiQuoteSelect
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiPreferences(PagedDialog): class GuiPreferences(PagedDialog):
def __init__(self, theParent): def __init__(self, theParent):
@@ -134,6 +134,7 @@ class GuiPreferences(PagedDialog):
# END Class GuiPreferences # END Class GuiPreferences
class GuiPreferencesGeneral(QWidget): class GuiPreferencesGeneral(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
@@ -153,7 +154,7 @@ class GuiPreferencesGeneral(QWidget):
self.mainForm.addGroupLabel(self.tr("Look and Feel")) self.mainForm.addGroupLabel(self.tr("Look and Feel"))
minWidth = self.mainConf.pxInt(200) minWidth = self.mainConf.pxInt(200)
## Select Locale # Select Locale
self.guiLang = QComboBox() self.guiLang = QComboBox()
self.guiLang.setMinimumWidth(minWidth) self.guiLang.setMinimumWidth(minWidth)
theLangs = self.mainConf.listLanguages(self.mainConf.LANG_NW) theLangs = self.mainConf.listLanguages(self.mainConf.LANG_NW)
@@ -169,7 +170,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("Changing this requires restarting novelWriter.") self.tr("Changing this requires restarting novelWriter.")
) )
## Select Theme # Select Theme
self.guiTheme = QComboBox() self.guiTheme = QComboBox()
self.guiTheme.setMinimumWidth(minWidth) self.guiTheme.setMinimumWidth(minWidth)
self.theThemes = self.theTheme.listThemes() self.theThemes = self.theTheme.listThemes()
@@ -185,7 +186,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("Changing this requires restarting novelWriter.") self.tr("Changing this requires restarting novelWriter.")
) )
## Select Icon Theme # Select Icon Theme
self.guiIcons = QComboBox() self.guiIcons = QComboBox()
self.guiIcons.setMinimumWidth(minWidth) self.guiIcons.setMinimumWidth(minWidth)
self.theIcons = self.theTheme.theIcons.listThemes() self.theIcons = self.theTheme.theIcons.listThemes()
@@ -201,7 +202,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("Changing this requires restarting novelWriter.") self.tr("Changing this requires restarting novelWriter.")
) )
## Dark Icons # Dark Icons
self.guiDark = QSwitch() self.guiDark = QSwitch()
self.guiDark.setChecked(self.mainConf.guiDark) self.guiDark.setChecked(self.mainConf.guiDark)
self.mainForm.addRow( self.mainForm.addRow(
@@ -210,7 +211,7 @@ class GuiPreferencesGeneral(QWidget):
self.tr("May improve the look of icons on dark themes.") self.tr("May improve the look of icons on dark themes.")
) )
## Font Family # Font Family
self.guiFont = QLineEdit() self.guiFont = QLineEdit()
self.guiFont.setReadOnly(True) self.guiFont.setReadOnly(True)
self.guiFont.setFixedWidth(self.mainConf.pxInt(162)) self.guiFont.setFixedWidth(self.mainConf.pxInt(162))
@@ -225,7 +226,7 @@ class GuiPreferencesGeneral(QWidget):
theButton = self.fontButton theButton = self.fontButton
) )
## Font Size # Font Size
self.guiFontSize = QSpinBox(self) self.guiFontSize = QSpinBox(self)
self.guiFontSize.setMinimum(8) self.guiFontSize.setMinimum(8)
self.guiFontSize.setMaximum(60) self.guiFontSize.setMaximum(60)
@@ -319,6 +320,7 @@ class GuiPreferencesGeneral(QWidget):
# END Class GuiPreferencesGeneral # END Class GuiPreferencesGeneral
class GuiPreferencesProjects(QWidget): class GuiPreferencesProjects(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
@@ -337,7 +339,7 @@ class GuiPreferencesProjects(QWidget):
# ============== # ==============
self.mainForm.addGroupLabel(self.tr("Automatic Save")) self.mainForm.addGroupLabel(self.tr("Automatic Save"))
## Document Save Timer # Document Save Timer
self.autoSaveDoc = QSpinBox(self) self.autoSaveDoc = QSpinBox(self)
self.autoSaveDoc.setMinimum(5) self.autoSaveDoc.setMinimum(5)
self.autoSaveDoc.setMaximum(600) self.autoSaveDoc.setMaximum(600)
@@ -350,7 +352,7 @@ class GuiPreferencesProjects(QWidget):
theUnit=self.tr("seconds") theUnit=self.tr("seconds")
) )
## Project Save Timer # Project Save Timer
self.autoSaveProj = QSpinBox(self) self.autoSaveProj = QSpinBox(self)
self.autoSaveProj.setMinimum(5) self.autoSaveProj.setMinimum(5)
self.autoSaveProj.setMaximum(600) self.autoSaveProj.setMaximum(600)
@@ -367,7 +369,7 @@ class GuiPreferencesProjects(QWidget):
# ============== # ==============
self.mainForm.addGroupLabel(self.tr("Project Backup")) self.mainForm.addGroupLabel(self.tr("Project Backup"))
## Backup Path # Backup Path
self.backupPath = self.mainConf.backupPath self.backupPath = self.mainConf.backupPath
self.backupGetPath = QPushButton(self.tr("Browse")) self.backupGetPath = QPushButton(self.tr("Browse"))
self.backupGetPath.clicked.connect(self._backupFolder) self.backupGetPath.clicked.connect(self._backupFolder)
@@ -377,7 +379,7 @@ class GuiPreferencesProjects(QWidget):
self.tr("Path: {0}").format(self.backupPath) self.tr("Path: {0}").format(self.backupPath)
) )
## Run when closing # Run when closing
self.backupOnClose = QSwitch() self.backupOnClose = QSwitch()
self.backupOnClose.setChecked(self.mainConf.backupOnClose) self.backupOnClose.setChecked(self.mainConf.backupOnClose)
self.backupOnClose.toggled.connect(self._toggledBackupOnClose) self.backupOnClose.toggled.connect(self._toggledBackupOnClose)
@@ -387,8 +389,8 @@ class GuiPreferencesProjects(QWidget):
self.tr("Can be overridden for individual projects in Project Settings.") self.tr("Can be overridden for individual projects in Project Settings.")
) )
## Ask before backup # Ask before backup
## Only enabled when "Run when closing" is checked # Only enabled when "Run when closing" is checked
self.askBeforeBackup = QSwitch() self.askBeforeBackup = QSwitch()
self.askBeforeBackup.setChecked(self.mainConf.askBeforeBackup) self.askBeforeBackup.setChecked(self.mainConf.askBeforeBackup)
self.askBeforeBackup.setEnabled(self.mainConf.backupOnClose) self.askBeforeBackup.setEnabled(self.mainConf.backupOnClose)
@@ -402,7 +404,7 @@ class GuiPreferencesProjects(QWidget):
# ============= # =============
self.mainForm.addGroupLabel(self.tr("Session Timer")) self.mainForm.addGroupLabel(self.tr("Session Timer"))
## Pause when idle # Pause when idle
self.stopWhenIdle = QSwitch() self.stopWhenIdle = QSwitch()
self.stopWhenIdle.setChecked(self.mainConf.stopWhenIdle) self.stopWhenIdle.setChecked(self.mainConf.stopWhenIdle)
self.mainForm.addRow( self.mainForm.addRow(
@@ -411,7 +413,7 @@ class GuiPreferencesProjects(QWidget):
self.tr("Also pauses when the application window does not have focus.") 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 = QDoubleSpinBox()
self.userIdleTime.setMinimum(0.5) self.userIdleTime.setMinimum(0.5)
self.userIdleTime.setMaximum(600.0) self.userIdleTime.setMaximum(600.0)
@@ -479,6 +481,7 @@ class GuiPreferencesProjects(QWidget):
# END Class GuiPreferencesProjects # END Class GuiPreferencesProjects
class GuiPreferencesDocuments(QWidget): class GuiPreferencesDocuments(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
@@ -497,7 +500,7 @@ class GuiPreferencesDocuments(QWidget):
# ========== # ==========
self.mainForm.addGroupLabel(self.tr("Text Style")) self.mainForm.addGroupLabel(self.tr("Text Style"))
## Font Family # Font Family
self.textFont = QLineEdit() self.textFont = QLineEdit()
self.textFont.setReadOnly(True) self.textFont.setReadOnly(True)
self.textFont.setFixedWidth(self.mainConf.pxInt(162)) self.textFont.setFixedWidth(self.mainConf.pxInt(162))
@@ -512,7 +515,7 @@ class GuiPreferencesDocuments(QWidget):
theButton = self.fontButton theButton = self.fontButton
) )
## Font Size # Font Size
self.textSize = QSpinBox(self) self.textSize = QSpinBox(self)
self.textSize.setMinimum(8) self.textSize.setMinimum(8)
self.textSize.setMaximum(60) self.textSize.setMaximum(60)
@@ -529,7 +532,7 @@ class GuiPreferencesDocuments(QWidget):
# ========= # =========
self.mainForm.addGroupLabel(self.tr("Text Flow")) 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 = QSpinBox(self)
self.textWidth.setMinimum(300) self.textWidth.setMinimum(300)
self.textWidth.setMaximum(10000) self.textWidth.setMaximum(10000)
@@ -542,7 +545,7 @@ class GuiPreferencesDocuments(QWidget):
theUnit=self.tr("px") theUnit=self.tr("px")
) )
## Max Text Width in Focus Mode # Max Text Width in Focus Mode
self.focusWidth = QSpinBox(self) self.focusWidth = QSpinBox(self)
self.focusWidth.setMinimum(300) self.focusWidth.setMinimum(300)
self.focusWidth.setMaximum(10000) self.focusWidth.setMaximum(10000)
@@ -555,7 +558,7 @@ class GuiPreferencesDocuments(QWidget):
theUnit=self.tr("px") theUnit=self.tr("px")
) )
## Document Fixed Width # Document Fixed Width
self.textFixedW = QSwitch() self.textFixedW = QSwitch()
self.textFixedW.setChecked(not self.mainConf.textFixedW) self.textFixedW.setChecked(not self.mainConf.textFixedW)
self.mainForm.addRow( self.mainForm.addRow(
@@ -564,7 +567,7 @@ class GuiPreferencesDocuments(QWidget):
self.tr("Text width is defined by the margins only.") self.tr("Text width is defined by the margins only.")
) )
## Focus Mode Footer # Focus Mode Footer
self.hideFocusFooter = QSwitch() self.hideFocusFooter = QSwitch()
self.hideFocusFooter.setChecked(self.mainConf.hideFocusFooter) self.hideFocusFooter.setChecked(self.mainConf.hideFocusFooter)
self.mainForm.addRow( self.mainForm.addRow(
@@ -573,7 +576,7 @@ class GuiPreferencesDocuments(QWidget):
self.tr("Hide the information bar at the bottom of the document.") self.tr("Hide the information bar at the bottom of the document.")
) )
## Justify Text # Justify Text
self.doJustify = QSwitch() self.doJustify = QSwitch()
self.doJustify.setChecked(self.mainConf.doJustify) self.doJustify.setChecked(self.mainConf.doJustify)
self.mainForm.addRow( self.mainForm.addRow(
@@ -582,7 +585,7 @@ class GuiPreferencesDocuments(QWidget):
self.tr("Lay out text with straight edges in the editor and viewer.") self.tr("Lay out text with straight edges in the editor and viewer.")
) )
## Document Margins # Document Margins
self.textMargin = QSpinBox(self) self.textMargin = QSpinBox(self)
self.textMargin.setMinimum(0) self.textMargin.setMinimum(0)
self.textMargin.setMaximum(900) self.textMargin.setMaximum(900)
@@ -595,7 +598,7 @@ class GuiPreferencesDocuments(QWidget):
theUnit=self.tr("px") theUnit=self.tr("px")
) )
## Tab Width # Tab Width
self.tabWidth = QSpinBox(self) self.tabWidth = QSpinBox(self)
self.tabWidth.setMinimum(0) self.tabWidth.setMinimum(0)
self.tabWidth.setMaximum(200) self.tabWidth.setMaximum(200)
@@ -649,6 +652,7 @@ class GuiPreferencesDocuments(QWidget):
# END Class GuiPreferencesDocuments # END Class GuiPreferencesDocuments
class GuiPreferencesEditor(QWidget): class GuiPreferencesEditor(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
@@ -669,7 +673,7 @@ class GuiPreferencesEditor(QWidget):
# ============== # ==============
self.mainForm.addGroupLabel(self.tr("Spell Checking")) self.mainForm.addGroupLabel(self.tr("Spell Checking"))
## Spell Check Provider and Language # Spell Check Provider and Language
self.spellLangList = QComboBox(self) self.spellLangList = QComboBox(self)
self.spellLangList.setMaximumWidth(mW) self.spellLangList.setMaximumWidth(mW)
@@ -699,7 +703,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Available languages are determined by your system.") self.tr("Available languages are determined by your system.")
) )
## Big Document Size Limit # Big Document Size Limit
self.bigDocLimit = QSpinBox(self) self.bigDocLimit = QSpinBox(self)
self.bigDocLimit.setMinimum(10) self.bigDocLimit.setMinimum(10)
self.bigDocLimit.setMaximum(10000) self.bigDocLimit.setMaximum(10000)
@@ -716,7 +720,7 @@ class GuiPreferencesEditor(QWidget):
# ========== # ==========
self.mainForm.addGroupLabel(self.tr("Word Count")) self.mainForm.addGroupLabel(self.tr("Word Count"))
## Word Count Timer # Word Count Timer
self.wordCountTimer = QDoubleSpinBox(self) self.wordCountTimer = QDoubleSpinBox(self)
self.wordCountTimer.setDecimals(1) self.wordCountTimer.setDecimals(1)
self.wordCountTimer.setMinimum(2.0) self.wordCountTimer.setMinimum(2.0)
@@ -734,7 +738,7 @@ class GuiPreferencesEditor(QWidget):
# ============== # ==============
self.mainForm.addGroupLabel(self.tr("Writing Guides")) self.mainForm.addGroupLabel(self.tr("Writing Guides"))
## Show Tabs and Spaces # Show Tabs and Spaces
self.showTabsNSpaces = QSwitch() self.showTabsNSpaces = QSwitch()
self.showTabsNSpaces.setChecked(self.mainConf.showTabsNSpaces) self.showTabsNSpaces.setChecked(self.mainConf.showTabsNSpaces)
self.mainForm.addRow( self.mainForm.addRow(
@@ -743,7 +747,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Add symbols to indicate tabs and spaces in the editor.") self.tr("Add symbols to indicate tabs and spaces in the editor.")
) )
## Show Line Endings # Show Line Endings
self.showLineEndings = QSwitch() self.showLineEndings = QSwitch()
self.showLineEndings.setChecked(self.mainConf.showLineEndings) self.showLineEndings.setChecked(self.mainConf.showLineEndings)
self.mainForm.addRow( self.mainForm.addRow(
@@ -756,7 +760,7 @@ class GuiPreferencesEditor(QWidget):
# ================ # ================
self.mainForm.addGroupLabel(self.tr("Scroll Behaviour")) self.mainForm.addGroupLabel(self.tr("Scroll Behaviour"))
## Scroll Past End # Scroll Past End
self.scrollPastEnd = QSwitch() self.scrollPastEnd = QSwitch()
self.scrollPastEnd.setChecked(self.mainConf.scrollPastEnd) self.scrollPastEnd.setChecked(self.mainConf.scrollPastEnd)
self.mainForm.addRow( self.mainForm.addRow(
@@ -765,7 +769,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Also improves trypewriter scrolling for short documents.") self.tr("Also improves trypewriter scrolling for short documents.")
) )
## Typewriter Scrolling # Typewriter Scrolling
self.autoScroll = QSwitch() self.autoScroll = QSwitch()
self.autoScroll.setChecked(self.mainConf.autoScroll) self.autoScroll.setChecked(self.mainConf.autoScroll)
self.mainForm.addRow( self.mainForm.addRow(
@@ -774,7 +778,7 @@ class GuiPreferencesEditor(QWidget):
self.tr("Try to keep the cursor at a fixed vertical position.") self.tr("Try to keep the cursor at a fixed vertical position.")
) )
## Typewriter Position # Typewriter Position
self.autoScrollPos = QSpinBox(self) self.autoScrollPos = QSpinBox(self)
self.autoScrollPos.setMinimum(10) self.autoScrollPos.setMinimum(10)
self.autoScrollPos.setMaximum(90) self.autoScrollPos.setMaximum(90)
@@ -849,6 +853,7 @@ class GuiPreferencesEditor(QWidget):
# END Class GuiPreferencesEditor # END Class GuiPreferencesEditor
class GuiPreferencesSyntax(QWidget): class GuiPreferencesSyntax(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
@@ -973,6 +978,7 @@ class GuiPreferencesSyntax(QWidget):
# END Class GuiPreferencesSyntax # END Class GuiPreferencesSyntax
class GuiPreferencesAutomation(QWidget): class GuiPreferencesAutomation(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
@@ -991,7 +997,7 @@ class GuiPreferencesAutomation(QWidget):
# ================== # ==================
self.mainForm.addGroupLabel(self.tr("Automatic Features")) self.mainForm.addGroupLabel(self.tr("Automatic Features"))
## Auto-Select Word Under Cursor # Auto-Select Word Under Cursor
self.autoSelect = QSwitch() self.autoSelect = QSwitch()
self.autoSelect.setChecked(self.mainConf.autoSelect) self.autoSelect.setChecked(self.mainConf.autoSelect)
self.mainForm.addRow( self.mainForm.addRow(
@@ -1000,7 +1006,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Apply formatting to word under cursor if no selection is made.") 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 = QSwitch()
self.doReplace.setChecked(self.mainConf.doReplace) self.doReplace.setChecked(self.mainConf.doReplace)
self.doReplace.toggled.connect(self._toggleAutoReplaceMain) self.doReplace.toggled.connect(self._toggleAutoReplaceMain)
@@ -1014,7 +1020,7 @@ class GuiPreferencesAutomation(QWidget):
# =================== # ===================
self.mainForm.addGroupLabel(self.tr("Replace as You Type")) self.mainForm.addGroupLabel(self.tr("Replace as You Type"))
## Auto-Replace Single Quotes # Auto-Replace Single Quotes
self.doReplaceSQuote = QSwitch() self.doReplaceSQuote = QSwitch()
self.doReplaceSQuote.setChecked(self.mainConf.doReplaceSQuote) self.doReplaceSQuote.setChecked(self.mainConf.doReplaceSQuote)
self.doReplaceSQuote.setEnabled(self.mainConf.doReplace) 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.") 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 = QSwitch()
self.doReplaceDQuote.setChecked(self.mainConf.doReplaceDQuote) self.doReplaceDQuote.setChecked(self.mainConf.doReplaceDQuote)
self.doReplaceDQuote.setEnabled(self.mainConf.doReplace) 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.") 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 = QSwitch()
self.doReplaceDash.setChecked(self.mainConf.doReplaceDash) self.doReplaceDash.setChecked(self.mainConf.doReplaceDash)
self.doReplaceDash.setEnabled(self.mainConf.doReplace) self.doReplaceDash.setEnabled(self.mainConf.doReplace)
@@ -1044,7 +1050,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Double and triple hyphens become short and long dashes.") self.tr("Double and triple hyphens become short and long dashes.")
) )
## Auto-Replace Dots # Auto-Replace Dots
self.doReplaceDots = QSwitch() self.doReplaceDots = QSwitch()
self.doReplaceDots.setChecked(self.mainConf.doReplaceDots) self.doReplaceDots.setChecked(self.mainConf.doReplaceDots)
self.doReplaceDots.setEnabled(self.mainConf.doReplace) self.doReplaceDots.setEnabled(self.mainConf.doReplace)
@@ -1058,7 +1064,7 @@ class GuiPreferencesAutomation(QWidget):
# ================= # =================
self.mainForm.addGroupLabel(self.tr("Automatic Padding")) self.mainForm.addGroupLabel(self.tr("Automatic Padding"))
## Pad Before # Pad Before
self.fmtPadBefore = QLineEdit() self.fmtPadBefore = QLineEdit()
self.fmtPadBefore.setMaxLength(32) self.fmtPadBefore.setMaxLength(32)
self.fmtPadBefore.setText(self.mainConf.fmtPadBefore) self.fmtPadBefore.setText(self.mainConf.fmtPadBefore)
@@ -1068,7 +1074,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Automatically add space before any of these symbols."), self.tr("Automatically add space before any of these symbols."),
) )
## Pad After # Pad After
self.fmtPadAfter = QLineEdit() self.fmtPadAfter = QLineEdit()
self.fmtPadAfter.setMaxLength(32) self.fmtPadAfter.setMaxLength(32)
self.fmtPadAfter.setText(self.mainConf.fmtPadAfter) self.fmtPadAfter.setText(self.mainConf.fmtPadAfter)
@@ -1078,7 +1084,7 @@ class GuiPreferencesAutomation(QWidget):
self.tr("Automatically add space after any of these symbols."), self.tr("Automatically add space after any of these symbols."),
) )
## Use Thin Space # Use Thin Space
self.fmtPadThin = QSwitch() self.fmtPadThin = QSwitch()
self.fmtPadThin.setChecked(self.mainConf.fmtPadThin) self.fmtPadThin.setChecked(self.mainConf.fmtPadThin)
self.fmtPadThin.setEnabled(self.mainConf.doReplace) self.fmtPadThin.setEnabled(self.mainConf.doReplace)
@@ -1129,6 +1135,7 @@ class GuiPreferencesAutomation(QWidget):
# END Class GuiPreferencesAutomation # END Class GuiPreferencesAutomation
class GuiPreferencesQuotes(QWidget): class GuiPreferencesQuotes(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
@@ -1151,7 +1158,7 @@ class GuiPreferencesQuotes(QWidget):
bWidth = int(2.5*self.theTheme.getTextWidth("...")) bWidth = int(2.5*self.theTheme.getTextWidth("..."))
self.quoteSym = {} self.quoteSym = {}
## Single Quote Style # Single Quote Style
self.quoteSym["SO"] = QLineEdit() self.quoteSym["SO"] = QLineEdit()
self.quoteSym["SO"].setMaxLength(1) self.quoteSym["SO"].setMaxLength(1)
self.quoteSym["SO"].setReadOnly(True) self.quoteSym["SO"].setReadOnly(True)
@@ -1184,7 +1191,7 @@ class GuiPreferencesQuotes(QWidget):
theButton=self.btnSingleStyleC theButton=self.btnSingleStyleC
) )
## Double Quote Style # Double Quote Style
self.quoteSym["DO"] = QLineEdit() self.quoteSym["DO"] = QLineEdit()
self.quoteSym["DO"].setMaxLength(1) self.quoteSym["DO"].setMaxLength(1)
self.quoteSym["DO"].setReadOnly(True) self.quoteSym["DO"].setReadOnly(True)
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Open Project novelWriter GUI Open Project
============================== ==============================
@@ -43,6 +42,7 @@ from nw.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiProjectLoad(QDialog): class GuiProjectLoad(QDialog):
NONE_STATE = 0 NONE_STATE = 0
+4 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Project Settings novelWriter GUI Project Settings
================================== ==================================
@@ -40,6 +39,7 @@ from nw.gui.custom import QSwitch, PagedDialog, QConfigLayout
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiProjectSettings(PagedDialog): class GuiProjectSettings(PagedDialog):
def __init__(self, theParent): def __init__(self, theParent):
@@ -156,6 +156,7 @@ class GuiProjectSettings(PagedDialog):
# END Class GuiProjectSettings # END Class GuiProjectSettings
class GuiProjectEditMain(QWidget): class GuiProjectEditMain(QWidget):
def __init__(self, theParent, theProject): def __init__(self, theParent, theProject):
@@ -239,6 +240,7 @@ class GuiProjectEditMain(QWidget):
# END Class GuiProjectEditMain # END Class GuiProjectEditMain
class GuiProjectEditStatus(QWidget): class GuiProjectEditStatus(QWidget):
COL_LABEL = 0 COL_LABEL = 0
@@ -487,6 +489,7 @@ class GuiProjectEditStatus(QWidget):
# END Class GuiProjectEditStatus # END Class GuiProjectEditStatus
class GuiProjectEditReplace(QWidget): class GuiProjectEditReplace(QWidget):
COL_KEY = 0 COL_KEY = 0
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Quotes Dialog novelWriter GUI Quotes Dialog
=============================== ===============================
@@ -38,6 +37,7 @@ from nw.constants import trConst, nwQuotes
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiQuoteSelect(QDialog): class GuiQuoteSelect(QDialog):
selectedQuote = "" selectedQuote = ""
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI User Wordlist novelWriter GUI User Wordlist
=============================== ===============================
@@ -39,6 +38,7 @@ from nw.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiWordList(QDialog): class GuiWordList(QDialog):
def __init__(self, theParent): def __init__(self, theParent):
+9 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Enums novelWriter Enums
=================== ===================
@@ -26,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
from enum import Enum from enum import Enum
class nwItemType(Enum): class nwItemType(Enum):
NO_TYPE = 0 NO_TYPE = 0
@@ -36,6 +36,7 @@ class nwItemType(Enum):
# END Enum nwItemType # END Enum nwItemType
class nwItemClass(Enum): class nwItemClass(Enum):
NO_CLASS = 0 NO_CLASS = 0
@@ -52,6 +53,7 @@ class nwItemClass(Enum):
# END Enum nwItemClass # END Enum nwItemClass
class nwItemLayout(Enum): class nwItemLayout(Enum):
NO_LAYOUT = 0 NO_LAYOUT = 0
@@ -66,6 +68,7 @@ class nwItemLayout(Enum):
# END Enum nwItemLayout # END Enum nwItemLayout
class nwDocAction(Enum): class nwDocAction(Enum):
NO_ACTION = 0 NO_ACTION = 0
@@ -98,6 +101,7 @@ class nwDocAction(Enum):
# END Enum nwDocAction # END Enum nwDocAction
class nwDocInsert(Enum): class nwDocInsert(Enum):
NO_INSERT = 0 NO_INSERT = 0
@@ -108,6 +112,7 @@ class nwDocInsert(Enum):
# END Enum nwDocInsert # END Enum nwDocInsert
class nwAlert(Enum): class nwAlert(Enum):
INFO = 0 INFO = 0
@@ -117,6 +122,7 @@ class nwAlert(Enum):
# END Enum nwAlert # END Enum nwAlert
class nwState(Enum): class nwState(Enum):
NONE = 0 NONE = 0
@@ -125,6 +131,7 @@ class nwState(Enum):
# END Enum nwState # END Enum nwState
class nwWidget(Enum): class nwWidget(Enum):
TREE = 1 TREE = 1
@@ -134,6 +141,7 @@ class nwWidget(Enum):
# END Enum nwWidget # END Enum nwWidget
class nwOutline(Enum): class nwOutline(Enum):
TITLE = 0 TITLE = 0
+3 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Exception Handling novelWriter Exception Handling
================================ ================================
@@ -35,6 +34,7 @@ from PyQt5.QtWidgets import (
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# =============================================================================================== # # =============================================================================================== #
# Utility Functions # Utility Functions
# =============================================================================================== # # =============================================================================================== #
@@ -45,6 +45,7 @@ def logException():
exType, exValue, _ = sys.exc_info() exType, exValue, _ = sys.exc_info()
logger.error("%s: %s" % (exType.__name__, str(exValue).strip("'"))) logger.error("%s: %s" % (exType.__name__, str(exValue).strip("'")))
# =============================================================================================== # # =============================================================================================== #
# Error Handler # Error Handler
# =============================================================================================== # # =============================================================================================== #
@@ -151,6 +152,7 @@ class NWErrorMessage(QDialog):
# END Class NWErrorMessage # END Class NWErrorMessage
def exceptionHandler(exType, exValue, exTrace): def exceptionHandler(exType, exValue, exTrace):
"""Function to catch unhandled global exceptions. """Function to catch unhandled global exceptions.
""" """
+20 -1
View File
@@ -1,4 +1,23 @@
# -*- coding: utf-8 -*- """
novelWriter GUI Init
======================
This file is a part of novelWriter
Copyright 20182021, 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 <https://www.gnu.org/licenses/>.
"""
from nw.gui.doceditor import GuiDocEditor from nw.gui.doceditor import GuiDocEditor
from nw.gui.docviewer import GuiDocViewer, GuiDocViewDetails from nw.gui.docviewer import GuiDocViewer, GuiDocViewDetails
+5 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Custom Widgets and Layouts novelWriter Custom Widgets and Layouts
======================================== ========================================
@@ -43,6 +42,7 @@ from nw.constants import nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# =============================================================================================== # # =============================================================================================== #
# Config Form Layout # Config Form Layout
# =============================================================================================== # # =============================================================================================== #
@@ -198,6 +198,7 @@ class QConfigLayout(QGridLayout):
# END Class QConfigLayout # END Class QConfigLayout
class QHelpLabel(QLabel): class QHelpLabel(QLabel):
def __init__(self, theText, textCol, fontSize=0.9): def __init__(self, theText, textCol, fontSize=0.9):
@@ -223,6 +224,7 @@ class QHelpLabel(QLabel):
# END Class QHelpLabel # END Class QHelpLabel
# =============================================================================================== # # =============================================================================================== #
# Switch Widget # Switch Widget
# =============================================================================================== # # =============================================================================================== #
@@ -367,6 +369,7 @@ class QSwitch(QAbstractButton):
# END Class QSwitch # END Class QSwitch
# =============================================================================================== # # =============================================================================================== #
# Paged Dialog w/Custom TabWidget # Paged Dialog w/Custom TabWidget
# =============================================================================================== # # =============================================================================================== #
@@ -417,6 +420,7 @@ class PagedDialog(QDialog):
# END Class PagedDialog # END Class PagedDialog
class VerticalTabBar(QTabBar): class VerticalTabBar(QTabBar):
def __init__(self, theParent=None): def __init__(self, theParent=None):
+7 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Document Editor novelWriter GUI Document Editor
================================= =================================
@@ -57,6 +56,7 @@ from nw.gui.dochighlight import GuiDocHighlighter
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiDocEditor(QTextEdit): class GuiDocEditor(QTextEdit):
MOVE_KEYS = ( MOVE_KEYS = (
@@ -1931,6 +1931,7 @@ class GuiDocEditor(QTextEdit):
# END Class GuiDocEditor # END Class GuiDocEditor
# =============================================================================================== # # =============================================================================================== #
# The Off-GUI Thread Word Counter # The Off-GUI Thread Word Counter
# A runnable for the word counter to be run in the thread pool off the main GUI thread. # 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 self._isRunning = False
return return
## END Class BackgroundWordCounter # END Class BackgroundWordCounter
class BackgroundWordCounterSignals(QObject): class BackgroundWordCounterSignals(QObject):
"""The QRunnable cannot emit a signal, so we need a simple QObject """The QRunnable cannot emit a signal, so we need a simple QObject
@@ -1970,6 +1972,7 @@ class BackgroundWordCounterSignals(QObject):
# END Class BackgroundWordCounterSignals # END Class BackgroundWordCounterSignals
# =============================================================================================== # # =============================================================================================== #
# The Embedded Document Search/Replace Feature # The Embedded Document Search/Replace Feature
# Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
@@ -2345,6 +2348,7 @@ class GuiDocEditSearch(QFrame):
# END Class GuiDocEditSearch # END Class GuiDocEditSearch
# =============================================================================================== # # =============================================================================================== #
# The Embedded Document Header # The Embedded Document Header
# Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport # 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 # END Class GuiDocEditHeader
# =============================================================================================== # # =============================================================================================== #
# The Embedded Document Footer # The Embedded Document Footer
# Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Syntax Highlighter novelWriter GUI Syntax Highlighter
==================================== ====================================
@@ -38,6 +37,7 @@ from nw.constants import nwRegEx, nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiDocHighlighter(QSyntaxHighlighter): class GuiDocHighlighter(QSyntaxHighlighter):
BLOCK_NONE = 0 BLOCK_NONE = 0
+5 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Document Viewer novelWriter GUI Document Viewer
================================= =================================
@@ -46,6 +45,7 @@ from nw.constants import nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiDocViewer(QTextBrowser): class GuiDocViewer(QTextBrowser):
def __init__(self, theParent): def __init__(self, theParent):
@@ -571,6 +571,7 @@ class GuiDocViewer(QTextBrowser):
# END Class GuiDocViewer # END Class GuiDocViewer
class GuiDocViewHistory(): class GuiDocViewHistory():
def __init__(self, docViewer): def __init__(self, docViewer):
@@ -702,6 +703,7 @@ class GuiDocViewHistory():
# END Class GuiDocViewHistory # END Class GuiDocViewHistory
# =============================================================================================== # # =============================================================================================== #
# The Embedded Document Header # The Embedded Document Header
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport # 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 # END Class GuiDocViewHeader
# =============================================================================================== # # =============================================================================================== #
# The Embedded Document Footer # The Embedded Document Footer
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport # 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 # END Class GuiDocViewFooter
# =============================================================================================== # # =============================================================================================== #
# The Document Back-Reference Panel # The Document Back-Reference Panel
# Placed in a separate QSplitter position in the main GUI window # Placed in a separate QSplitter position in the main GUI window
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Item Details Panel novelWriter GUI Item Details Panel
==================================== ====================================
@@ -36,6 +35,7 @@ from nw.constants import trConst, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiItemDetails(QWidget): class GuiItemDetails(QWidget):
def __init__(self, theParent): def __init__(self, theParent):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Main Menu novelWriter GUI Main Menu
=========================== ===========================
@@ -36,6 +35,7 @@ from nw.constants import trConst, nwKeyWords, nwLabels, nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiMainMenu(QMenuBar): class GuiMainMenu(QMenuBar):
def __init__(self, theParent): def __init__(self, theParent):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Novel Tree novelWriter GUI Novel Tree
============================ ============================
@@ -37,6 +36,7 @@ from nw.constants import nwKeyWords
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiNovelTree(QTreeWidget): class GuiNovelTree(QTreeWidget):
C_TITLE = 0 C_TITLE = 0
+2 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Project Outline novelWriter GUI Project Outline
================================= =================================
@@ -39,6 +38,7 @@ from nw.constants import trConst, nwKeyWords, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiOutline(QTreeWidget): class GuiOutline(QTreeWidget):
DEF_WIDTH = { DEF_WIDTH = {
@@ -467,6 +467,7 @@ class GuiOutline(QTreeWidget):
# END Class GuiOutline # END Class GuiOutline
class GuiOutlineHeaderMenu(QMenu): class GuiOutlineHeaderMenu(QMenu):
def __init__(self, theParent): def __init__(self, theParent):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Project Outline Details novelWriter GUI Project Outline Details
========================================= =========================================
@@ -37,6 +36,7 @@ from nw.constants import trConst, nwKeyWords, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiOutlineDetails(QScrollArea): class GuiOutlineDetails(QScrollArea):
LVL_MAP = { LVL_MAP = {
+3 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Project Details novelWriter GUI Project Details
================================= =================================
@@ -41,6 +40,7 @@ from nw.gui.custom import PagedDialog, QSwitch
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiProjectDetails(PagedDialog): class GuiProjectDetails(PagedDialog):
def __init__(self, theParent): def __init__(self, theParent):
@@ -128,6 +128,7 @@ class GuiProjectDetails(PagedDialog):
# END Class GuiProjectDetails # END Class GuiProjectDetails
class GuiProjectDetailsMain(QWidget): class GuiProjectDetailsMain(QWidget):
def __init__(self, theParent, theProject): def __init__(self, theParent, theProject):
@@ -241,6 +242,7 @@ class GuiProjectDetailsMain(QWidget):
# END Class GuiProjectDetailsMain # END Class GuiProjectDetailsMain
class GuiProjectDetailsContents(QWidget): class GuiProjectDetailsContents(QWidget):
C_TITLE = 0 C_TITLE = 0
+2 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Project Tree novelWriter GUI Project Tree
============================== ==============================
@@ -42,6 +41,7 @@ from nw.constants import nwConst, trConst, nwLists, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiProjectTree(QTreeWidget): class GuiProjectTree(QTreeWidget):
C_NAME = 0 C_NAME = 0
@@ -1102,6 +1102,7 @@ class GuiProjectTree(QTreeWidget):
# END Class GuiProjectTree # END Class GuiProjectTree
class GuiProjectTreeMenu(QMenu): class GuiProjectTreeMenu(QMenu):
def __init__(self, theTree): def __init__(self, theTree):
+8 -7
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Main Window Status Bar novelWriter GUI Main Window Status Bar
======================================== ========================================
@@ -38,6 +37,7 @@ from nw.enum import nwState
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiMainStatus(QStatusBar): class GuiMainStatus(QStatusBar):
def __init__(self, theParent): def __init__(self, theParent):
@@ -62,7 +62,7 @@ class GuiMainStatus(QStatusBar):
xM = self.mainConf.pxInt(8) xM = self.mainConf.pxInt(8)
## The Spell Checker Language # The Spell Checker Language
self.langIcon = QLabel("") self.langIcon = QLabel("")
self.langText = QLabel(self.tr("None")) self.langText = QLabel(self.tr("None"))
self.langIcon.setPixmap(self.theTheme.getPixmap("status_lang", (iPx, iPx))) self.langIcon.setPixmap(self.theTheme.getPixmap("status_lang", (iPx, iPx)))
@@ -71,7 +71,7 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.langIcon) self.addPermanentWidget(self.langIcon)
self.addPermanentWidget(self.langText) self.addPermanentWidget(self.langText)
## The Editor Status # The Editor Status
self.docIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self) self.docIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
self.docText = QLabel(self.tr("Editor")) self.docText = QLabel(self.tr("Editor"))
self.docIcon.setContentsMargins(0, 0, 0, 0) self.docIcon.setContentsMargins(0, 0, 0, 0)
@@ -79,7 +79,7 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.docIcon) self.addPermanentWidget(self.docIcon)
self.addPermanentWidget(self.docText) self.addPermanentWidget(self.docText)
## The Project Status # The Project Status
self.projIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self) self.projIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
self.projText = QLabel(self.tr("Project")) self.projText = QLabel(self.tr("Project"))
self.projIcon.setContentsMargins(0, 0, 0, 0) self.projIcon.setContentsMargins(0, 0, 0, 0)
@@ -87,7 +87,7 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.projIcon) self.addPermanentWidget(self.projIcon)
self.addPermanentWidget(self.projText) self.addPermanentWidget(self.projText)
## The Project and Session Stats # The Project and Session Stats
self.statsIcon = QLabel() self.statsIcon = QLabel()
self.statsText = QLabel("") self.statsText = QLabel("")
self.statsIcon.setPixmap(self.theTheme.getPixmap("status_stats", (iPx, iPx))) self.statsIcon.setPixmap(self.theTheme.getPixmap("status_stats", (iPx, iPx)))
@@ -96,8 +96,8 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.statsIcon) self.addPermanentWidget(self.statsIcon)
self.addPermanentWidget(self.statsText) self.addPermanentWidget(self.statsText)
## The Session Clock # The Session Clock
### Set the mimimum width so the label doesn't rescale every second # Set the mimimum width so the label doesn't rescale every second
self.timePixmap = self.theTheme.getPixmap("status_time", (iPx, iPx)) self.timePixmap = self.theTheme.getPixmap("status_time", (iPx, iPx))
self.idlePixmap = self.theTheme.getPixmap("status_idle", (iPx, iPx)) self.idlePixmap = self.theTheme.getPixmap("status_idle", (iPx, iPx))
@@ -235,6 +235,7 @@ class GuiMainStatus(QStatusBar):
# END Class GuiMainStatus # END Class GuiMainStatus
class StatusLED(QAbstractButton): class StatusLED(QAbstractButton):
def __init__(self, colNone, colGood, colBad, sW, sH, parent=None): def __init__(self, colNone, colGood, colBad, sW, sH, parent=None):
+16 -14
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Theme and Icons Classes novelWriter Theme and Icons Classes
===================================== =====================================
@@ -43,6 +42,7 @@ from nw.enum import nwAlert
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# =============================================================================================== # # =============================================================================================== #
# Gui Theme Class # Gui Theme Class
# Handles the look and feel of novelWriter # Handles the look and feel of novelWriter
@@ -65,8 +65,9 @@ class GuiTheme:
self.syntaxList = [] self.syntaxList = []
# Loaded Theme Settings # Loaded Theme Settings
# =====================
## Theme # Theme
self.themeName = "" self.themeName = ""
self.themeDescription = "" self.themeDescription = ""
self.themeAuthor = "" self.themeAuthor = ""
@@ -75,7 +76,7 @@ class GuiTheme:
self.themeLicense = "" self.themeLicense = ""
self.themeLicenseUrl = "" self.themeLicenseUrl = ""
## GUI # GUI
self.statNone = [120, 120, 120] self.statNone = [120, 120, 120]
self.statUnsaved = [200, 15, 39] self.statUnsaved = [200, 15, 39]
self.statSaved = [2, 133, 37] self.statSaved = [2, 133, 37]
@@ -83,7 +84,7 @@ class GuiTheme:
# Loaded Syntax Settings # Loaded Syntax Settings
## Main # Main
self.syntaxName = "" self.syntaxName = ""
self.syntaxDescription = "" self.syntaxDescription = ""
self.syntaxAuthor = "" self.syntaxAuthor = ""
@@ -92,7 +93,7 @@ class GuiTheme:
self.syntaxLicense = "" self.syntaxLicense = ""
self.syntaxLicenseUrl = "" self.syntaxLicenseUrl = ""
## Colours # Colours
self.colBack = [255, 255, 255] self.colBack = [255, 255, 255]
self.colText = [0, 0, 0] self.colText = [0, 0, 0]
self.colLink = [0, 0, 0] self.colLink = [0, 0, 0]
@@ -288,7 +289,7 @@ class GuiTheme:
nw.logException() nw.logException()
return False return False
## Main # Main
cnfSec = "Main" cnfSec = "Main"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self.themeName = self._parseLine(confParser, cnfSec, "name", "") self.themeName = self._parseLine(confParser, cnfSec, "name", "")
@@ -299,7 +300,7 @@ class GuiTheme:
self.themeLicense = self._parseLine(confParser, cnfSec, "license", "N/A") self.themeLicense = self._parseLine(confParser, cnfSec, "license", "N/A")
self.themeLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "") self.themeLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
## Palette # Palette
cnfSec = "Palette" cnfSec = "Palette"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self._setPalette(confParser, cnfSec, "window", QPalette.Window) self._setPalette(confParser, cnfSec, "window", QPalette.Window)
@@ -317,7 +318,7 @@ class GuiTheme:
self._setPalette(confParser, cnfSec, "link", QPalette.Link) self._setPalette(confParser, cnfSec, "link", QPalette.Link)
self._setPalette(confParser, cnfSec, "linkvisited", QPalette.LinkVisited) self._setPalette(confParser, cnfSec, "linkvisited", QPalette.LinkVisited)
## GUI # GUI
cnfSec = "GUI" cnfSec = "GUI"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self.statNone = self._loadColour(confParser, cnfSec, "statusnone") self.statNone = self._loadColour(confParser, cnfSec, "statusnone")
@@ -346,7 +347,7 @@ class GuiTheme:
nw.logException() nw.logException()
return False return False
## Main # Main
cnfSec = "Main" cnfSec = "Main"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self.syntaxName = self._parseLine(confParser, cnfSec, "name", "") self.syntaxName = self._parseLine(confParser, cnfSec, "name", "")
@@ -357,7 +358,7 @@ class GuiTheme:
self.syntaxLicense = self._parseLine(confParser, cnfSec, "license", "") self.syntaxLicense = self._parseLine(confParser, cnfSec, "license", "")
self.syntaxLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "") self.syntaxLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
## Syntax # Syntax
cnfSec = "Syntax" cnfSec = "Syntax"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self.colBack = self._loadColour(confParser, cnfSec, "background") self.colBack = self._loadColour(confParser, cnfSec, "background")
@@ -496,6 +497,7 @@ class GuiTheme:
# End Class GuiTheme # End Class GuiTheme
# =============================================================================================== # # =============================================================================================== #
# Icons Class # Icons Class
# =============================================================================================== # # =============================================================================================== #
@@ -560,7 +562,7 @@ class GuiIcons:
"search_cancel" : (None, None), "search_cancel" : (None, None),
"search_preserve" : (None, None), "search_preserve" : (None, None),
## General Button Icons # General Button Icons
"folder-open" : (QStyle.SP_DirOpenIcon, "folder-open"), "folder-open" : (QStyle.SP_DirOpenIcon, "folder-open"),
"delete" : (QStyle.SP_DialogDiscardButton, "edit-delete"), "delete" : (QStyle.SP_DialogDiscardButton, "edit-delete"),
"close" : (QStyle.SP_DialogCloseButton, "window-close"), "close" : (QStyle.SP_DialogCloseButton, "window-close"),
@@ -583,7 +585,7 @@ class GuiIcons:
"forward" : (None, None), "forward" : (None, None),
"settings" : (None, None), "settings" : (None, None),
## Switches # Switches
"sticky-on" : (None, None), "sticky-on" : (None, None),
"sticky-off" : (None, None), "sticky-off" : (None, None),
"bullet-on" : (None, None), "bullet-on" : (None, None),
@@ -651,7 +653,7 @@ class GuiIcons:
nw.logException() nw.logException()
return False return False
## Main # Main
cnfSec = "Main" cnfSec = "Main"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self.themeName = self._parseLine(confParser, cnfSec, "name", "") self.themeName = self._parseLine(confParser, cnfSec, "name", "")
@@ -662,7 +664,7 @@ class GuiIcons:
self.themeLicense = self._parseLine(confParser, cnfSec, "license", "N/A") self.themeLicense = self._parseLine(confParser, cnfSec, "license", "N/A")
self.themeLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "") self.themeLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
## Palette # Palette
cnfSec = "Map" cnfSec = "Map"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
for iconName, iconFile in confParser.items(cnfSec): for iconName, iconFile in confParser.items(cnfSec):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Main Window novelWriter GUI Main Window
============================= =============================
@@ -55,6 +54,7 @@ from nw.constants import nwLists
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiMain(QMainWindow): class GuiMain(QMainWindow):
def __init__(self): def __init__(self):
+20 -1
View File
@@ -1,4 +1,23 @@
# -*- coding: utf-8 -*- """
novelWriter Tools Init
========================
This file is a part of novelWriter
Copyright 20182021, 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 <https://www.gnu.org/licenses/>.
"""
from nw.tools.build import GuiBuildNovel from nw.tools.build import GuiBuildNovel
from nw.tools.projwizard import GuiProjectWizard from nw.tools.projwizard import GuiProjectWizard
+3 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Build Novel Project novelWriter GUI Build Novel Project
===================================== =====================================
@@ -52,6 +51,7 @@ from nw.gui.custom import QSwitch
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiBuildNovel(QDialog): class GuiBuildNovel(QDialog):
FMT_PDF = 1 # Print to PDF FMT_PDF = 1 # Print to PDF
@@ -215,7 +215,7 @@ class GuiBuildNovel(QDialog):
self.fontForm = QGridLayout(self) self.fontForm = QGridLayout(self)
self.fontGroup.setLayout(self.fontForm) self.fontGroup.setLayout(self.fontForm)
## Font Family # Font Family
self.textFont = QLineEdit() self.textFont = QLineEdit()
self.textFont.setReadOnly(True) self.textFont.setReadOnly(True)
self.textFont.setMinimumWidth(xFmt) self.textFont.setMinimumWidth(xFmt)
@@ -1182,6 +1182,7 @@ class GuiBuildNovel(QDialog):
# END Class GuiBuildNovel # END Class GuiBuildNovel
class GuiBuildNovelDocView(QTextBrowser): class GuiBuildNovelDocView(QTextBrowser):
def __init__(self, theParent, theProject): def __init__(self, theParent, theProject):
+6 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI New Project Wizard novelWriter GUI New Project Wizard
==================================== ====================================
@@ -48,6 +47,7 @@ PAGE_POP = 2
PAGE_CUSTOM = 3 PAGE_CUSTOM = 3
PAGE_FINAL = 4 PAGE_FINAL = 4
class GuiProjectWizard(QWizard): class GuiProjectWizard(QWizard):
def __init__(self, theParent): def __init__(self, theParent):
@@ -86,6 +86,7 @@ class GuiProjectWizard(QWizard):
# END Class GuiProjectWizard # END Class GuiProjectWizard
class ProjWizardIntroPage(QWizardPage): class ProjWizardIntroPage(QWizardPage):
def __init__(self, theWizard): def __init__(self, theWizard):
@@ -155,6 +156,7 @@ class ProjWizardIntroPage(QWizardPage):
# END Class ProjWizardIntroPage # END Class ProjWizardIntroPage
class ProjWizardFolderPage(QWizardPage): class ProjWizardFolderPage(QWizardPage):
def __init__(self, theWizard): def __init__(self, theWizard):
@@ -227,6 +229,7 @@ class ProjWizardFolderPage(QWizardPage):
# END Class ProjWizardFolderPage # END Class ProjWizardFolderPage
class ProjWizardPopulatePage(QWizardPage): class ProjWizardPopulatePage(QWizardPage):
def __init__(self, theWizard): def __init__(self, theWizard):
@@ -282,6 +285,7 @@ class ProjWizardPopulatePage(QWizardPage):
# END Class ProjWizardPopulatePage # END Class ProjWizardPopulatePage
class ProjWizardCustomPage(QWizardPage): class ProjWizardCustomPage(QWizardPage):
def __init__(self, theWizard): def __init__(self, theWizard):
@@ -400,6 +404,7 @@ class ProjWizardCustomPage(QWizardPage):
# END Class ProjWizardCustomPage # END Class ProjWizardCustomPage
class ProjWizardFinalPage(QWizardPage): class ProjWizardFinalPage(QWizardPage):
def __init__(self, theWizard): def __init__(self, theWizard):
+1 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Writing Statistics novelWriter GUI Writing Statistics
==================================== ====================================
@@ -45,6 +44,7 @@ from nw.gui.custom import QSwitch
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiWritingStats(QDialog): class GuiWritingStats(QDialog):
C_TIME = 0 C_TIME = 0
+1 -1
View File
@@ -49,6 +49,6 @@ gui_scripts =
universal = 0 universal = 0
[flake8] [flake8]
ignore = E203,E221,E226,E228,E241,E251,E261,E266,E302,E305 ignore = E203,E221,E226,E228,E241,E251
max-line-length = 99 max-line-length = 99
exclude = docs/* exclude = docs/*
+15 -1
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" """
novelWriter Main Setup Script novelWriter Main Setup Script
=============================== ===============================
@@ -35,6 +34,7 @@ OS_LINUX = 1
OS_WIN = 2 OS_WIN = 2
OS_DARWIN = 3 OS_DARWIN = 3
# =============================================================================================== # # =============================================================================================== #
# Utilities # Utilities
# =============================================================================================== # # =============================================================================================== #
@@ -66,6 +66,7 @@ def extractVersion():
return numVers, hexVers return numVers, hexVers
# =============================================================================================== # # =============================================================================================== #
# General # General
# =============================================================================================== # # =============================================================================================== #
@@ -102,6 +103,7 @@ def installPackages(hostOS):
return return
## ##
# Clean Build and Dist Folders (clean) # Clean Build and Dist Folders (clean)
## ##
@@ -140,6 +142,7 @@ def cleanInstall():
return return
# =============================================================================================== # # =============================================================================================== #
# Additional Buiilds # Additional Buiilds
# =============================================================================================== # # =============================================================================================== #
@@ -217,6 +220,7 @@ def buildQtDocs():
return return
## ##
# Qt Linguist QM Builder (qtlrelease) # Qt Linguist QM Builder (qtlrelease)
## ##
@@ -255,6 +259,7 @@ def buildQtI18n():
return return
## ##
# Qt Linguist TS Builder (qtlupdate) # Qt Linguist TS Builder (qtlupdate)
## ##
@@ -278,6 +283,7 @@ def buildQtI18nTS():
return return
## ##
# Sample Project ZIP File Builder (sample) # Sample Project ZIP File Builder (sample)
## ##
@@ -318,6 +324,7 @@ def buildSampleZip():
return return
# =============================================================================================== # # =============================================================================================== #
# Python Packaging # Python Packaging
# =============================================================================================== # # =============================================================================================== #
@@ -429,6 +436,7 @@ def makeMinimalPackage(targetOS):
return return
## ##
# Make Simple Package (pack-pyz) # Make Simple Package (pack-pyz)
## ##
@@ -607,6 +615,7 @@ def makeSimplePackage(embedPython):
return return
# =============================================================================================== # # =============================================================================================== #
# General Installers # General Installers
# =============================================================================================== # # =============================================================================================== #
@@ -754,6 +763,7 @@ def xdgInstall():
return return
## ##
# XDG Uninstallation (xdg-uninstall) # XDG Uninstallation (xdg-uninstall)
## ##
@@ -823,6 +833,7 @@ def xdgUninstall():
return return
## ##
# WIN Installation (win-install) # WIN Installation (win-install)
## ##
@@ -947,6 +958,7 @@ def winInstall():
return return
## ##
# WIN Uninstallation (win-uninstall) # WIN Uninstallation (win-uninstall)
## ##
@@ -1033,6 +1045,7 @@ def winUninstall():
return return
# =============================================================================================== # # =============================================================================================== #
# Windows Installers # Windows Installers
# =============================================================================================== # # =============================================================================================== #
@@ -1070,6 +1083,7 @@ def innoSetup():
return return
# =============================================================================================== # # =============================================================================================== #
# Process Command Line # Process Command Line
# =============================================================================================== # # =============================================================================================== #
+13 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Test Suite Configuration novelWriter Test Suite Configuration
====================================== ======================================
@@ -34,6 +33,7 @@ import nw # noqa: E402
from nw.config import Config # noqa: E402 from nw.config import Config # noqa: E402
## ##
# Core Test Folders # Core Test Folders
## ##
@@ -52,6 +52,7 @@ def tmpDir():
os.mkdir(theDir) os.mkdir(theDir)
return theDir return theDir
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def refDir(): def refDir():
"""The folder where all the reference files are stored for verifying """The folder where all the reference files are stored for verifying
@@ -61,6 +62,7 @@ def refDir():
theDir = os.path.join(testDir, "reference") theDir = os.path.join(testDir, "reference")
return theDir return theDir
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def filesDir(): def filesDir():
"""The folder where additional test files are stored. """The folder where additional test files are stored.
@@ -69,6 +71,7 @@ def filesDir():
theDir = os.path.join(testDir, "files") theDir = os.path.join(testDir, "files")
return theDir return theDir
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def outDir(tmpDir): def outDir(tmpDir):
"""An output folder for test results """An output folder for test results
@@ -78,6 +81,7 @@ def outDir(tmpDir):
os.mkdir(theDir) os.mkdir(theDir)
return theDir return theDir
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def fncDir(tmpDir): def fncDir(tmpDir):
"""A temporary folder for a single test function. """A temporary folder for a single test function.
@@ -92,6 +96,7 @@ def fncDir(tmpDir):
shutil.rmtree(fncDir) shutil.rmtree(fncDir)
return return
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def fncProj(fncDir): def fncProj(fncDir):
"""A temporary folder for a single test function, """A temporary folder for a single test function,
@@ -104,6 +109,7 @@ def fncProj(fncDir):
os.mkdir(prjDir) os.mkdir(prjDir)
return prjDir return prjDir
## ##
# novelWriter Objects # novelWriter Objects
## ##
@@ -121,6 +127,7 @@ def tmpConf(tmpDir):
theConf.guiLang = "en_GB" theConf.guiLang = "en_GB"
return theConf return theConf
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def fncConf(fncDir): def fncConf(fncDir):
"""Create a temporary novelWriter configuration object. """Create a temporary novelWriter configuration object.
@@ -134,6 +141,7 @@ def fncConf(fncDir):
theConf.guiLang = "en_GB" theConf.guiLang = "en_GB"
return theConf return theConf
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def dummyGUI(monkeypatch, tmpConf): def dummyGUI(monkeypatch, tmpConf):
"""Create a mock instance of novelWriter's main GUI class. """Create a mock instance of novelWriter's main GUI class.
@@ -143,6 +151,7 @@ def dummyGUI(monkeypatch, tmpConf):
theGui.mainConf = tmpConf theGui.mainConf = tmpConf
return theGui return theGui
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def nwGUI(qtbot, monkeypatch, fncDir, fncConf): def nwGUI(qtbot, monkeypatch, fncDir, fncConf):
"""Create an instance of the novelWriter GUI. """Create an instance of the novelWriter GUI.
@@ -164,6 +173,7 @@ def nwGUI(qtbot, monkeypatch, fncDir, fncConf):
return return
## ##
# Temp Project Folders # Temp Project Folders
## ##
@@ -188,6 +198,7 @@ def nwMinimal(tmpDir):
return return
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def nwLipsum(tmpDir): def nwLipsum(tmpDir):
"""A medium sized novelWriter example project with a lot of Lorem """A medium sized novelWriter example project with a lot of Lorem
@@ -209,6 +220,7 @@ def nwLipsum(tmpDir):
return return
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def nwOldProj(tmpDir): def nwOldProj(tmpDir):
"""A minimal movelWriter project using the old folder structure used """A minimal movelWriter project using the old folder structure used
+5 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Test Suite Mocked Classes 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 <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
# =========================================================================== # # =========================================================================== #
# Mock GUI # Mock GUI
# =========================================================================== # # =========================================================================== #
@@ -79,6 +79,7 @@ class MockGuiMain():
# END Class MockGuiMain # END Class MockGuiMain
class MockStatusBar(): class MockStatusBar():
def __init__(self): def __init__(self):
@@ -92,6 +93,7 @@ class MockStatusBar():
# END Class MockStatusBar # END Class MockStatusBar
class MockApp: class MockApp:
def __init__(self): def __init__(self):
@@ -102,6 +104,7 @@ class MockApp:
# END Class MockApp # END Class MockApp
# =========================================================================== # # =========================================================================== #
# Error Functions # Error Functions
# Mock functions that will raise errors instead. # Mock functions that will raise errors instead.
@@ -110,5 +113,6 @@ class MockApp:
def causeOSError(*args, **kwargs): def causeOSError(*args, **kwargs):
raise OSError("OSError") raise OSError("OSError")
def causeException(*args, **kwargs): def causeException(*args, **kwargs):
raise Exception("Exception") raise Exception("Exception")
+17 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Common Functions Tester novelWriter Common Functions Tester
===================================== =====================================
@@ -30,6 +29,7 @@ from nw.common import (
isItemLayout, numberToRoman isItemLayout, numberToRoman
) )
@pytest.mark.base @pytest.mark.base
def testBaseCommon_CheckString(): def testBaseCommon_CheckString():
"""Test the checkString function. """Test the checkString function.
@@ -44,6 +44,7 @@ def testBaseCommon_CheckString():
# END Test testBaseCommon_CheckString # END Test testBaseCommon_CheckString
@pytest.mark.base @pytest.mark.base
def testBaseCommon_CheckInt(): def testBaseCommon_CheckInt():
"""Test the checkInt function. """Test the checkInt function.
@@ -57,6 +58,7 @@ def testBaseCommon_CheckInt():
# END Test testBaseCommon_CheckInt # END Test testBaseCommon_CheckInt
@pytest.mark.base @pytest.mark.base
def testBaseCommon_CheckBool(): def testBaseCommon_CheckBool():
"""Test the checkBool function. """Test the checkBool function.
@@ -75,6 +77,7 @@ def testBaseCommon_CheckBool():
# END Test testBaseCommon_CheckBool # END Test testBaseCommon_CheckBool
@pytest.mark.base @pytest.mark.base
def testBaseCommon_CheckHandle(): def testBaseCommon_CheckHandle():
"""Test the checkHandle function. """Test the checkHandle function.
@@ -88,6 +91,7 @@ def testBaseCommon_CheckHandle():
# END Test testBaseCommon_CheckHandle # END Test testBaseCommon_CheckHandle
@pytest.mark.base @pytest.mark.base
def testBaseCommon_IsHandle(): def testBaseCommon_IsHandle():
"""Test the isHandle function. """Test the isHandle function.
@@ -102,6 +106,7 @@ def testBaseCommon_IsHandle():
# END Test testBaseCommon_IsHandle # END Test testBaseCommon_IsHandle
@pytest.mark.base @pytest.mark.base
def testBaseCommon_IsTitleTag(): def testBaseCommon_IsTitleTag():
"""Test the isItemClass function. """Test the isItemClass function.
@@ -119,6 +124,7 @@ def testBaseCommon_IsTitleTag():
# END Test testBaseCommon_IsTitleTag # END Test testBaseCommon_IsTitleTag
@pytest.mark.base @pytest.mark.base
def testBaseCommon_IsItemClass(): def testBaseCommon_IsItemClass():
"""Test the isItemClass function. """Test the isItemClass function.
@@ -141,6 +147,7 @@ def testBaseCommon_IsItemClass():
# END Test testBaseCommon_IsItemClass # END Test testBaseCommon_IsItemClass
@pytest.mark.base @pytest.mark.base
def testBaseCommon_IsItemType(): def testBaseCommon_IsItemType():
"""Test the isItemType function. """Test the isItemType function.
@@ -157,6 +164,7 @@ def testBaseCommon_IsItemType():
# END Test testBaseCommon_IsItemType # END Test testBaseCommon_IsItemType
@pytest.mark.base @pytest.mark.base
def testBaseCommon_IsItemLayout(): def testBaseCommon_IsItemLayout():
"""Test the isItemLayout function. """Test the isItemLayout function.
@@ -177,6 +185,7 @@ def testBaseCommon_IsItemLayout():
# END Test testBaseCommon_IsItemLayout # END Test testBaseCommon_IsItemLayout
@pytest.mark.base @pytest.mark.base
def testBaseCommon_HexToInt(): def testBaseCommon_HexToInt():
"""Test the hexToInt function. """Test the hexToInt function.
@@ -190,6 +199,7 @@ def testBaseCommon_HexToInt():
# END Test testBaseCommon_HexToInt # END Test testBaseCommon_HexToInt
@pytest.mark.base @pytest.mark.base
def testBaseCommon_FormatTimeStamp(): def testBaseCommon_FormatTimeStamp():
"""Test the formatTimeStamp function. """Test the formatTimeStamp function.
@@ -200,6 +210,7 @@ def testBaseCommon_FormatTimeStamp():
# END Test testBaseCommon_FormatTimeStamp # END Test testBaseCommon_FormatTimeStamp
@pytest.mark.base @pytest.mark.base
def testBaseCommon_FormatTime(): def testBaseCommon_FormatTime():
"""Test the formatTime function. """Test the formatTime function.
@@ -222,6 +233,7 @@ def testBaseCommon_FormatTime():
# END Test testBaseCommon_FormatTime # END Test testBaseCommon_FormatTime
@pytest.mark.base @pytest.mark.base
def testBaseCommon_FormatInt(): def testBaseCommon_FormatInt():
"""Test the formatInt function. """Test the formatInt function.
@@ -237,6 +249,7 @@ def testBaseCommon_FormatInt():
# END Test testBaseCommon_FormatInt # END Test testBaseCommon_FormatInt
@pytest.mark.base @pytest.mark.base
def testBaseCommon_TransferCase(): def testBaseCommon_TransferCase():
"""Test the transferCase function. """Test the transferCase function.
@@ -251,6 +264,7 @@ def testBaseCommon_TransferCase():
# END Test testBaseCommon_TransferCase # END Test testBaseCommon_TransferCase
@pytest.mark.base @pytest.mark.base
def testBaseCommon_FuzzyTime(): def testBaseCommon_FuzzyTime():
"""Test the fuzzyTime function. """Test the fuzzyTime function.
@@ -286,6 +300,7 @@ def testBaseCommon_FuzzyTime():
# END Test testBaseCommon_FuzzyTime # END Test testBaseCommon_FuzzyTime
@pytest.mark.base @pytest.mark.base
def testBaseCommon_MakeFileNameSafe(): def testBaseCommon_MakeFileNameSafe():
"""Test the fuzzyTime function. """Test the fuzzyTime function.
@@ -297,6 +312,7 @@ def testBaseCommon_MakeFileNameSafe():
# END Test testBaseCommon_MakeFileNameSafe # END Test testBaseCommon_MakeFileNameSafe
@pytest.mark.core @pytest.mark.core
def testBaseCommon_RomanNumbers(): def testBaseCommon_RomanNumbers():
"""Test conversion of integers to Roman numbers. """Test conversion of integers to Roman numbers.
+8 -3
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Config Class Tester novelWriter Config Class Tester
================================= =================================
@@ -33,6 +32,7 @@ from tools import cmpFiles, writeFile
from nw.config import Config from nw.config import Config
from nw.constants import nwConst, nwFiles from nw.constants import nwConst, nwFiles
@pytest.mark.base @pytest.mark.base
def testBaseConfig_Constructor(monkeypatch): def testBaseConfig_Constructor(monkeypatch):
"""Test config contructor. """Test config contructor.
@@ -79,6 +79,7 @@ def testBaseConfig_Constructor(monkeypatch):
# END Test testBaseConfig_Constructor # END Test testBaseConfig_Constructor
@pytest.mark.base @pytest.mark.base
def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir): def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
"""Test config intialisation. """Test config intialisation.
@@ -95,7 +96,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
# Let the config class figure out the path # Let the config class figure out the path
with monkeypatch.context() as mp: 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.verQtValue = 50600
tstConf.initConfig() tstConf.initConfig()
assert tstConf.confPath == os.path.join(fncDir, tstConf.appHandle) 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 # Run again and set the paths directly and correctly
# This should create a config file as well # This should create a config file as well
with monkeypatch.context() as mp: 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.spellTool = nwConst.SP_INTERNAL
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir) tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
assert tstConf.confPath == tmpDir assert tstConf.confPath == tmpDir
@@ -205,6 +206,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
# END Test testBaseConfig_Init # END Test testBaseConfig_Init
@pytest.mark.base @pytest.mark.base
def testBaseConfig_RecentCache(monkeypatch, tmpConf, tmpDir, fncDir): def testBaseConfig_RecentCache(monkeypatch, tmpConf, tmpDir, fncDir):
"""Test recent cache file. """Test recent cache file.
@@ -266,6 +268,7 @@ def testBaseConfig_RecentCache(monkeypatch, tmpConf, tmpDir, fncDir):
# END Test testBaseConfig_RecentCache # END Test testBaseConfig_RecentCache
@pytest.mark.base @pytest.mark.base
def testBaseConfig_SetPath(tmpConf, tmpDir): def testBaseConfig_SetPath(tmpConf, tmpDir):
"""Test path setters. """Test path setters.
@@ -297,6 +300,7 @@ def testBaseConfig_SetPath(tmpConf, tmpDir):
# END Test testBaseConfig_SetPath # END Test testBaseConfig_SetPath
@pytest.mark.base @pytest.mark.base
def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir): def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir):
"""Set various sizes and positions """Set various sizes and positions
@@ -470,6 +474,7 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir):
# END Test testBaseConfig_SettersGetters # END Test testBaseConfig_SettersGetters
@pytest.mark.base @pytest.mark.base
def testBaseConfig_Internal(monkeypatch, tmpConf): def testBaseConfig_Internal(monkeypatch, tmpConf):
"""Check internal functions. """Check internal functions.
+10 -9
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Error Handler Tester novelWriter Error Handler Tester
================================== ==================================
@@ -29,6 +28,7 @@ from mock import causeException
from nw.error import NWErrorMessage, exceptionHandler from nw.error import NWErrorMessage, exceptionHandler
@pytest.mark.base @pytest.mark.base
def testBaseError_Dialog(qtbot, monkeypatch, fncDir, tmpDir): def testBaseError_Dialog(qtbot, monkeypatch, fncDir, tmpDir):
"""Test the error dialog. """Test the error dialog.
@@ -71,6 +71,7 @@ def testBaseError_Dialog(qtbot, monkeypatch, fncDir, tmpDir):
# END Test testBaseError_Dialog # END Test testBaseError_Dialog
@pytest.mark.base @pytest.mark.base
def testBaseError_Handler(qtbot, monkeypatch, fncDir, tmpDir): def testBaseError_Handler(qtbot, monkeypatch, fncDir, tmpDir):
"""Test the error handler. This test doesn'thave any asserts, but it """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 # Normal shutdown
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(NWErrorMessage, "exec_", lambda *args: None) mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None) mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
exceptionHandler(Exception, "Error Message", None) exceptionHandler(Exception, "Error Message", None)
# Should not crash when no GUI is found # Should not crash when no GUI is found
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(NWErrorMessage, "exec_", lambda *args: None) mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None) mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", lambda: []) mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", lambda: [])
exceptionHandler(Exception, "Error Message", None) exceptionHandler(Exception, "Error Message", None)
# Should handle qApp failing # Should handle qApp failing
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(NWErrorMessage, "exec_", lambda *args: None) mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None) mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", causeException) mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", causeException)
exceptionHandler(Exception, "Error Message", None) exceptionHandler(Exception, "Error Message", None)
# Should handle failing to close main GUI # Should handle failing to close main GUI
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(NWErrorMessage, "exec_", lambda *args: None) mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *args: None) mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None)
mp.setattr(nwGUI, "closeMain", causeException) mp.setattr(nwGUI, "closeMain", causeException)
exceptionHandler(Exception, "Error Message", None) exceptionHandler(Exception, "Error Message", None)
+3 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Main Init Tester novelWriter Main Init Tester
============================== ==============================
@@ -27,6 +26,7 @@ import sys
from mock import MockGuiMain from mock import MockGuiMain
@pytest.mark.base @pytest.mark.base
def testBaseInit_Launch(caplog, monkeypatch, tmpDir): def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
"""Check launching the main GUI. """Check launching the main GUI.
@@ -64,6 +64,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
# END Test testBaseInit_Launch # END Test testBaseInit_Launch
@pytest.mark.base @pytest.mark.base
def testBaseInit_Options(monkeypatch, tmpDir): def testBaseInit_Options(monkeypatch, tmpDir):
"""Test command line options for logging level. """Test command line options for logging level.
@@ -136,6 +137,7 @@ def testBaseInit_Options(monkeypatch, tmpDir):
# END Test testBaseInit_Options # END Test testBaseInit_Options
@pytest.mark.base @pytest.mark.base
def testBaseInit_Imports(caplog, monkeypatch, tmpDir): def testBaseInit_Imports(caplog, monkeypatch, tmpDir):
"""Check import error handling. """Check import error handling.
+3 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter NWDoc Class Tester novelWriter NWDoc Class Tester
================================ ================================
@@ -28,6 +27,7 @@ from mock import causeOSError
from nw.core import NWProject, NWDoc from nw.core import NWProject, NWDoc
from nw.enum import nwItemClass, nwItemLayout from nw.enum import nwItemClass, nwItemLayout
@pytest.mark.core @pytest.mark.core
def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal): def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal):
"""Test loading and saving a document with the NWDoc class. """Test loading and saving a document with the NWDoc class.
@@ -120,8 +120,9 @@ def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal):
# END Test testCoreDocument_Load # END Test testCoreDocument_Load
@pytest.mark.core @pytest.mark.core
def testCoreDocument_Methods(monkeypatch, dummyGUI, nwMinimal): def testCoreDocument_Methods(dummyGUI, nwMinimal):
"""Test other methods of the NWDoc class. """Test other methods of the NWDoc class.
""" """
theProject = NWProject(dummyGUI) theProject = NWProject(dummyGUI)
+10 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter NWIndex Class Tester novelWriter NWIndex Class Tester
================================== ==================================
@@ -33,6 +32,7 @@ from nw.core.project import NWProject
from nw.core.index import NWIndex, countWords from nw.core.index import NWIndex, countWords
from nw.enum import nwItemClass, nwItemLayout from nw.enum import nwItemClass, nwItemLayout
@pytest.mark.core @pytest.mark.core
def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir): def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir):
"""Test core functionality of scaning, saving, loading and checking """Test core functionality of scaning, saving, loading and checking
@@ -124,6 +124,7 @@ def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir):
# END Test testCoreIndex_LoadSave # END Test testCoreIndex_LoadSave
@pytest.mark.core @pytest.mark.core
def testCoreIndex_ScanThis(nwMinimal, dummyGUI): def testCoreIndex_ScanThis(nwMinimal, dummyGUI):
"""Test the tag scanner function scanThis. """Test the tag scanner function scanThis.
@@ -175,6 +176,7 @@ def testCoreIndex_ScanThis(nwMinimal, dummyGUI):
# END Test testCoreIndex_ScanThis # END Test testCoreIndex_ScanThis
@pytest.mark.core @pytest.mark.core
def testCoreIndex_CheckThese(nwMinimal, dummyGUI): def testCoreIndex_CheckThese(nwMinimal, dummyGUI):
"""Test the tag checker function checkThese. """Test the tag checker function checkThese.
@@ -236,6 +238,7 @@ def testCoreIndex_CheckThese(nwMinimal, dummyGUI):
# END Test testCoreIndex_CheckThese # END Test testCoreIndex_CheckThese
@pytest.mark.core @pytest.mark.core
def testCoreIndex_ScanText(nwMinimal, dummyGUI): def testCoreIndex_ScanText(nwMinimal, dummyGUI):
"""Check the index text scanner. """Check the index text scanner.
@@ -441,6 +444,7 @@ def testCoreIndex_ScanText(nwMinimal, dummyGUI):
# END Test testCoreIndex_ScanText # END Test testCoreIndex_ScanText
@pytest.mark.core @pytest.mark.core
def testCoreIndex_ExtractData(nwMinimal, dummyGUI): def testCoreIndex_ExtractData(nwMinimal, dummyGUI):
"""Check the index data extraction functions. """Check the index data extraction functions.
@@ -673,6 +677,7 @@ def testCoreIndex_ExtractData(nwMinimal, dummyGUI):
# END Test testCoreIndex_ExtractData # END Test testCoreIndex_ExtractData
@pytest.mark.core @pytest.mark.core
def testCoreIndex_CheckTagIndex(dummyGUI): def testCoreIndex_CheckTagIndex(dummyGUI):
"""Test the tag index checker. """Test the tag index checker.
@@ -737,6 +742,7 @@ def testCoreIndex_CheckTagIndex(dummyGUI):
# END Test testCoreIndex_CheckTagIndex # END Test testCoreIndex_CheckTagIndex
@pytest.mark.core @pytest.mark.core
def testCoreIndex_CheckRefIndex(dummyGUI): def testCoreIndex_CheckRefIndex(dummyGUI):
"""Test the reference index checker. """Test the reference index checker.
@@ -859,6 +865,7 @@ def testCoreIndex_CheckRefIndex(dummyGUI):
# END Test testCoreIndex_CheckRefIndex # END Test testCoreIndex_CheckRefIndex
@pytest.mark.core @pytest.mark.core
def testCoreIndex_CheckNovelNoteIndex(dummyGUI): def testCoreIndex_CheckNovelNoteIndex(dummyGUI):
"""Test the novel and note index checkers. """Test the novel and note index checkers.
@@ -1117,6 +1124,7 @@ def testCoreIndex_CheckNovelNoteIndex(dummyGUI):
# END Test testCoreIndex_CheckNovelNoteIndex # END Test testCoreIndex_CheckNovelNoteIndex
@pytest.mark.core @pytest.mark.core
def testCoreIndex_CheckTextCounts(dummyGUI): def testCoreIndex_CheckTextCounts(dummyGUI):
"""Test the text counts checker. """Test the text counts checker.
@@ -1173,6 +1181,7 @@ def testCoreIndex_CheckTextCounts(dummyGUI):
# END Test testCoreIndex_CheckTextCounts # END Test testCoreIndex_CheckTextCounts
@pytest.mark.core @pytest.mark.core
def testCoreIndex_CountWords(): def testCoreIndex_CountWords():
"""Test the word counter and the exclusion filers. """Test the word counter and the exclusion filers.
+9 -4
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter NWItem Class Tester novelWriter NWItem Class Tester
================================= =================================
@@ -28,6 +27,7 @@ from nw.core import NWProject
from nw.core.item import NWItem from nw.core.item import NWItem
from nw.enum import nwItemClass, nwItemType, nwItemLayout from nw.enum import nwItemClass, nwItemType, nwItemLayout
@pytest.mark.core @pytest.mark.core
def testCoreItem_Setters(dummyGUI): def testCoreItem_Setters(dummyGUI):
"""Test all the simple setters for the NWItem class. """Test all the simple setters for the NWItem class.
@@ -165,6 +165,7 @@ def testCoreItem_Setters(dummyGUI):
# END Test testCoreItem_Setters # END Test testCoreItem_Setters
@pytest.mark.core @pytest.mark.core
def testCoreItem_TypeSetter(dummyGUI): def testCoreItem_TypeSetter(dummyGUI):
"""Test the setter for all the nwItemType values for the NWItem """Test the setter for all the nwItemType values for the NWItem
@@ -193,6 +194,7 @@ def testCoreItem_TypeSetter(dummyGUI):
# END Test testCoreItem_TypeSetter # END Test testCoreItem_TypeSetter
@pytest.mark.core @pytest.mark.core
def testCoreItem_ClassSetter(dummyGUI): def testCoreItem_ClassSetter(dummyGUI):
"""Test the setter for all the nwItemClass values for the NWItem """Test the setter for all the nwItemClass values for the NWItem
@@ -233,6 +235,7 @@ def testCoreItem_ClassSetter(dummyGUI):
# END Test testCoreItem_ClassSetter # END Test testCoreItem_ClassSetter
@pytest.mark.core @pytest.mark.core
def testCoreItem_LayoutSetter(dummyGUI): def testCoreItem_LayoutSetter(dummyGUI):
"""Test the setter for all the nwItemLayout values for the NWItem """Test the setter for all the nwItemLayout values for the NWItem
@@ -269,6 +272,7 @@ def testCoreItem_LayoutSetter(dummyGUI):
# END Test testCoreItem_LayoutSetter # END Test testCoreItem_LayoutSetter
@pytest.mark.core @pytest.mark.core
def testCoreItem_XMLPackUnpack(dummyGUI, caplog): def testCoreItem_XMLPackUnpack(dummyGUI, caplog):
"""Test packing and unpacking XML objects for the NWItem class. """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 assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
# Errors # Errors
# ======
## Not an Item # Not an Item
mockXml = etree.SubElement(nwXML, "stuff") mockXml = etree.SubElement(nwXML, "stuff")
assert theItem.unpackXML(mockXml) is False assert theItem.unpackXML(mockXml) is False
## Item without Handle # Item without Handle
mockXml = etree.SubElement(nwXML, "item", attrib={"stuff": "nah"}) mockXml = etree.SubElement(nwXML, "item", attrib={"stuff": "nah"})
assert theItem.unpackXML(mockXml) is False 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"}) mockXml = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"})
xParam = etree.SubElement(mockXml, "invalid") xParam = etree.SubElement(mockXml, "invalid")
xParam.text = "stuff" xParam.text = "stuff"
+3 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter OptionState Class Tester novelWriter OptionState Class Tester
====================================== ======================================
@@ -30,6 +29,7 @@ from nw.core import NWProject
from nw.core.options import OptionState from nw.core.options import OptionState
from nw.constants import nwFiles from nw.constants import nwFiles
@pytest.mark.core @pytest.mark.core
def testCoreOptions_LoadSave(monkeypatch, dummyGUI, tmpDir): def testCoreOptions_LoadSave(monkeypatch, dummyGUI, tmpDir):
"""Test loading and saving from the OptionState class. """Test loading and saving from the OptionState class.
@@ -100,8 +100,9 @@ def testCoreOptions_LoadSave(monkeypatch, dummyGUI, tmpDir):
# END Test testCoreOptions_LoadSave # END Test testCoreOptions_LoadSave
@pytest.mark.core @pytest.mark.core
def testCoreOptions_SetGet(monkeypatch, dummyGUI, tmpDir): def testCoreOptions_SetGet(dummyGUI):
"""Test setting and getting values from the OptionState class. """Test setting and getting values from the OptionState class.
""" """
theProject = NWProject(dummyGUI) theProject = NWProject(dummyGUI)
+20 -4
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter NWProject Class Tester novelWriter NWProject Class Tester
==================================== ====================================
@@ -35,8 +34,9 @@ from nw.enum import nwItemClass, nwItemType, nwItemLayout
from nw.common import formatTimeStamp from nw.common import formatTimeStamp
from nw.constants import nwFiles from nw.constants import nwFiles
@pytest.mark.core @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 """Create a new project from a project wizard dictionary. With
default setting, creating a Minimal project. default setting, creating a Minimal project.
""" """
@@ -83,6 +83,7 @@ def testCoreProject_NewMinimal(fncDir, outDir, refDir, tmpDir, dummyGUI):
# END Test testCoreProject_NewMinimal # END Test testCoreProject_NewMinimal
@pytest.mark.core @pytest.mark.core
def testCoreProject_NewCustomA(fncDir, outDir, refDir, dummyGUI): def testCoreProject_NewCustomA(fncDir, outDir, refDir, dummyGUI):
"""Create a new project from a project wizard dictionary. """Create a new project from a project wizard dictionary.
@@ -124,6 +125,7 @@ def testCoreProject_NewCustomA(fncDir, outDir, refDir, dummyGUI):
# END Test testCoreProject_NewCustomA # END Test testCoreProject_NewCustomA
@pytest.mark.core @pytest.mark.core
def testCoreProject_NewCustomB(fncDir, outDir, refDir, dummyGUI): def testCoreProject_NewCustomB(fncDir, outDir, refDir, dummyGUI):
"""Create a new project from a project wizard dictionary. """Create a new project from a project wizard dictionary.
@@ -165,6 +167,7 @@ def testCoreProject_NewCustomB(fncDir, outDir, refDir, dummyGUI):
# END Test testCoreProject_NewCustomB # END Test testCoreProject_NewCustomB
@pytest.mark.core @pytest.mark.core
def testCoreProject_NewSampleA(fncDir, tmpConf, dummyGUI, tmpDir): def testCoreProject_NewSampleA(fncDir, tmpConf, dummyGUI, tmpDir):
"""Check that we can create a new project can be created from the """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 # END Test testCoreProject_NewSampleA
@pytest.mark.core @pytest.mark.core
def testCoreProject_NewSampleB(monkeypatch, fncDir, tmpConf, dummyGUI, tmpDir): def testCoreProject_NewSampleB(monkeypatch, fncDir, tmpConf, dummyGUI, tmpDir):
"""Check that we can create a new project can be created from the """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 # END Test testCoreProject_NewSampleB
@pytest.mark.core @pytest.mark.core
def testCoreProject_NewRoot(fncDir, outDir, refDir, dummyGUI): def testCoreProject_NewRoot(fncDir, outDir, refDir, dummyGUI):
"""Check that new root folders can be added to the project. """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 # END Test testCoreProject_NewRoot
@pytest.mark.core @pytest.mark.core
def testCoreProject_NewFile(fncDir, outDir, refDir, dummyGUI): def testCoreProject_NewFile(fncDir, outDir, refDir, dummyGUI):
"""Check that new files can be added to the project. """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 # END Test testCoreProject_NewFile
@pytest.mark.core @pytest.mark.core
def testCoreProject_Open(monkeypatch, nwMinimal, dummyGUI): def testCoreProject_Open(monkeypatch, nwMinimal, dummyGUI):
"""Test opening a project. """Test opening a project.
@@ -436,6 +443,7 @@ def testCoreProject_Open(monkeypatch, nwMinimal, dummyGUI):
# END Test testCoreProject_Open # END Test testCoreProject_Open
@pytest.mark.core @pytest.mark.core
def testCoreProject_Save(monkeypatch, nwMinimal, dummyGUI, refDir): def testCoreProject_Save(monkeypatch, nwMinimal, dummyGUI, refDir):
"""Test saving a project. """Test saving a project.
@@ -481,6 +489,7 @@ def testCoreProject_Save(monkeypatch, nwMinimal, dummyGUI, refDir):
# END Test testCoreProject_Save # END Test testCoreProject_Save
@pytest.mark.core @pytest.mark.core
def testCoreProject_LockFile(monkeypatch, fncDir, dummyGUI): def testCoreProject_LockFile(monkeypatch, fncDir, dummyGUI):
"""Test lock file functions for the project folder. """Test lock file functions for the project folder.
@@ -540,6 +549,7 @@ def testCoreProject_LockFile(monkeypatch, fncDir, dummyGUI):
# END Test testCoreProject_LockFile # END Test testCoreProject_LockFile
@pytest.mark.core @pytest.mark.core
def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI): def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI):
"""Test helper functions for the project folder. """Test helper functions for the project folder.
@@ -554,7 +564,7 @@ def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI):
# Block user's home folder # Block user's home folder
with monkeypatch.context() as mp: 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 assert theProject.ensureFolderStructure() is False
# Create a file to block meta folder # Create a file to block meta folder
@@ -583,6 +593,7 @@ def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI):
# END Test testCoreProject_Helpers # END Test testCoreProject_Helpers
@pytest.mark.core @pytest.mark.core
def testCoreProject_AccessItems(nwMinimal, dummyGUI): def testCoreProject_AccessItems(nwMinimal, dummyGUI):
"""Test helper functions for the project folder. """Test helper functions for the project folder.
@@ -642,6 +653,7 @@ def testCoreProject_AccessItems(nwMinimal, dummyGUI):
# END Test testCoreProject_AccessItems # END Test testCoreProject_AccessItems
@pytest.mark.core @pytest.mark.core
def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir): def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
"""Test other project class methods and functions. """Test other project class methods and functions.
@@ -839,7 +851,7 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
# Session stats # Session stats
with monkeypatch.context() as mp: 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) assert not theProject._appendSessionStats(idleTime=0)
# Block open # Block open
@@ -892,6 +904,7 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
# END Test testCoreProject_Methods # END Test testCoreProject_Methods
@pytest.mark.core @pytest.mark.core
def testCoreProject_OrphanedFiles(dummyGUI, nwLipsum): def testCoreProject_OrphanedFiles(dummyGUI, nwLipsum):
"""Check that files in the content folder that are not tracked in """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 # END Test testCoreProject_OrphanedFiles
@pytest.mark.core @pytest.mark.core
def testCoreProject_OldFormat(dummyGUI, nwOldProj): def testCoreProject_OldFormat(dummyGUI, nwOldProj):
"""Test that a project folder structure of version 1.0 can be """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 # END Test testCoreProject_OldFormat
@pytest.mark.core @pytest.mark.core
def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir): def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir):
"""Test the functins that handle legacy data folders and structure """Test the functins that handle legacy data folders and structure
@@ -1162,6 +1177,7 @@ def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir):
# END Test testCoreProject_LegacyData # END Test testCoreProject_LegacyData
@pytest.mark.core @pytest.mark.core
def testCoreProject_Backup(monkeypatch, dummyGUI, nwMinimal, tmpDir): def testCoreProject_Backup(monkeypatch, dummyGUI, nwMinimal, tmpDir):
"""Test the automated backup feature of the project class. The test """Test the automated backup feature of the project class. The test
+3 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Spell Check Classes Tester novelWriter Spell Check Classes Tester
======================================== ========================================
@@ -29,6 +28,7 @@ from tools import readFile, writeFile
from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple
@pytest.mark.core @pytest.mark.core
def testCoreSpell_Super(monkeypatch, tmpDir): def testCoreSpell_Super(monkeypatch, tmpDir):
"""Test the spell checker super class """Test the spell checker super class
@@ -70,6 +70,7 @@ def testCoreSpell_Super(monkeypatch, tmpDir):
# END Test testCoreSpell_Super # END Test testCoreSpell_Super
@pytest.mark.core @pytest.mark.core
def testCoreSpell_Enchant(monkeypatch, tmpDir): def testCoreSpell_Enchant(monkeypatch, tmpDir):
"""Test the pyenchant spell checker """Test the pyenchant spell checker
@@ -114,6 +115,7 @@ def testCoreSpell_Enchant(monkeypatch, tmpDir):
# END Test testCoreSpell_Enchant # END Test testCoreSpell_Enchant
@pytest.mark.core @pytest.mark.core
def testCoreSpell_Simple(monkeypatch, tmpDir): def testCoreSpell_Simple(monkeypatch, tmpDir):
"""Test the fallback simple spell checker """Test the fallback simple spell checker
+2 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter NWStatus Class Tester novelWriter NWStatus Class Tester
=================================== ===================================
@@ -26,6 +25,7 @@ from lxml import etree
from nw.core.status import NWStatus from nw.core.status import NWStatus
@pytest.mark.core @pytest.mark.core
def testCoreStatus_Entries(): def testCoreStatus_Entries():
"""Test all the simple setters for the NWItem class. """Test all the simple setters for the NWItem class.
@@ -100,6 +100,7 @@ def testCoreStatus_Entries():
# END Test testCoreStatus_Entries # END Test testCoreStatus_Entries
@pytest.mark.core @pytest.mark.core
def testCoreStatus_XMLPackUnpack(): def testCoreStatus_XMLPackUnpack():
"""Test all the simple setters for the NWItem class. """Test all the simple setters for the NWItem class.
+5 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter ToHtml Class Tester novelWriter ToHtml Class Tester
================================= =================================
@@ -27,6 +26,7 @@ from tools import readFile
from nw.core import NWProject, NWIndex, ToHtml from nw.core import NWProject, NWIndex, ToHtml
@pytest.mark.core @pytest.mark.core
def testCoreToHtml_Format(dummyGUI): def testCoreToHtml_Format(dummyGUI):
"""Test all the formatters for the ToHtml class. """Test all the formatters for the ToHtml class.
@@ -79,6 +79,7 @@ def testCoreToHtml_Format(dummyGUI):
# END Test testCoreToHtml_Format # END Test testCoreToHtml_Format
@pytest.mark.core @pytest.mark.core
def testCoreToHtml_Convert(dummyGUI): def testCoreToHtml_Convert(dummyGUI):
"""Test the converter of the ToHtml class. """Test the converter of the ToHtml class.
@@ -344,6 +345,8 @@ def testCoreToHtml_Convert(dummyGUI):
# END Test testCoreToHtml_Convert # END Test testCoreToHtml_Convert
@pytest.mark.core
def testCoreToHtml_Complex(dummyGUI, fncDir): def testCoreToHtml_Complex(dummyGUI, fncDir):
"""Test the ave method of the ToHtml class. """Test the ave method of the ToHtml class.
""" """
@@ -416,6 +419,7 @@ def testCoreToHtml_Complex(dummyGUI, fncDir):
# END Test testCoreToHtml_Save # END Test testCoreToHtml_Save
@pytest.mark.core @pytest.mark.core
def testCoreToHtml_Methods(dummyGUI): def testCoreToHtml_Methods(dummyGUI):
"""Test all the other methods of the ToHtml class. """Test all the other methods of the ToHtml class.
+4 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Tokenizer Class Tester novelWriter Tokenizer Class Tester
==================================== ====================================
@@ -28,6 +27,7 @@ from tools import readFile
from nw.core import NWProject, NWDoc from nw.core import NWProject, NWDoc
from nw.core.tokenizer import Tokenizer from nw.core.tokenizer import Tokenizer
@pytest.mark.core @pytest.mark.core
def testCoreToken_Setters(dummyGUI): def testCoreToken_Setters(dummyGUI):
"""Test all the setters for the Tokenizer class. """Test all the setters for the Tokenizer class.
@@ -111,6 +111,7 @@ def testCoreToken_Setters(dummyGUI):
# END Test testCoreToken_Setters # END Test testCoreToken_Setters
@pytest.mark.core @pytest.mark.core
def testCoreToken_TextOps(monkeypatch, nwMinimal, dummyGUI): def testCoreToken_TextOps(monkeypatch, nwMinimal, dummyGUI):
"""Test handling files and text in the Tokenizer class. """Test handling files and text in the Tokenizer class.
@@ -193,6 +194,7 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, dummyGUI):
# END Test testCoreToken_TextOps # END Test testCoreToken_TextOps
@pytest.mark.core @pytest.mark.core
def testCoreToken_Tokenize(dummyGUI): def testCoreToken_Tokenize(dummyGUI):
"""Test the tokenization of the Tokenizer class. """Test the tokenization of the Tokenizer class.
@@ -494,6 +496,7 @@ def testCoreToken_Tokenize(dummyGUI):
# END Test testCoreToken_Tokenize # END Test testCoreToken_Tokenize
@pytest.mark.core @pytest.mark.core
def testCoreToken_Headers(dummyGUI): def testCoreToken_Headers(dummyGUI):
"""Test the header and page parser of the Tokenizer class. """Test the header and page parser of the Tokenizer class.
+2 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter ToOdt Class Tester novelWriter ToOdt Class Tester
================================= =================================
@@ -35,6 +34,7 @@ XML_NS = [
' xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"', ' xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"',
] ]
def xmlToText(xElem): def xmlToText(xElem):
"""Get the text content of an XML element. """Get the text content of an XML element.
""" """
@@ -43,6 +43,7 @@ def xmlToText(xElem):
rTxt = rTxt.replace(nSpace, "") rTxt = rTxt.replace(nSpace, "")
return rTxt return rTxt
@pytest.mark.core @pytest.mark.core
def testCoreToOdt_Convert(dummyGUI): def testCoreToOdt_Convert(dummyGUI):
"""Test the converter of the ToHtml class. """Test the converter of the ToHtml class.
+9 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter NWTree Class Tester 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.enum import nwItemClass, nwItemType, nwItemLayout
from nw.constants import nwFiles from nw.constants import nwFiles
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def dummyItems(dummyGUI): def dummyItems(dummyGUI):
"""Create a list of mock items. """Create a list of mock items.
@@ -106,6 +106,7 @@ def dummyItems(dummyGUI):
return theItems return theItems
@pytest.mark.core @pytest.mark.core
def testCoreTree_BuildTree(dummyGUI, dummyItems): def testCoreTree_BuildTree(dummyGUI, dummyItems):
"""Test building a project tree from a list of items. """Test building a project tree from a list of items.
@@ -202,6 +203,7 @@ def testCoreTree_BuildTree(dummyGUI, dummyItems):
# END Test testCoreTree_BuildTree # END Test testCoreTree_BuildTree
@pytest.mark.core @pytest.mark.core
def testCoreTree_Methods(dummyGUI, dummyItems): def testCoreTree_Methods(dummyGUI, dummyItems):
"""Test bvarious class methods. """Test bvarious class methods.
@@ -258,6 +260,7 @@ def testCoreTree_Methods(dummyGUI, dummyItems):
# END Test testCoreTree_Methods # END Test testCoreTree_Methods
@pytest.mark.core @pytest.mark.core
def testCoreTree_UpdateItemLayout(dummyGUI, dummyItems): def testCoreTree_UpdateItemLayout(dummyGUI, dummyItems):
"""Test building a project tree from a list of items. """Test building a project tree from a list of items.
@@ -383,6 +386,7 @@ def testCoreTree_UpdateItemLayout(dummyGUI, dummyItems):
# END Test testCoreTree_UpdateItemLayout # END Test testCoreTree_UpdateItemLayout
@pytest.mark.core @pytest.mark.core
def testCoreTree_MakeHandles(monkeypatch, dummyGUI): def testCoreTree_MakeHandles(monkeypatch, dummyGUI):
"""Test generating item handles. """Test generating item handles.
@@ -425,6 +429,7 @@ def testCoreTree_MakeHandles(monkeypatch, dummyGUI):
# END Test testCoreTree_MakeHandles # END Test testCoreTree_MakeHandles
@pytest.mark.core @pytest.mark.core
def testCoreTree_Stats(dummyGUI, dummyItems): def testCoreTree_Stats(dummyGUI, dummyItems):
"""Test project stats methods. """Test project stats methods.
@@ -451,6 +456,7 @@ def testCoreTree_Stats(dummyGUI, dummyItems):
# END Test testCoreTree_Stats # END Test testCoreTree_Stats
@pytest.mark.core @pytest.mark.core
def testCoreTree_Reorder(dummyGUI, dummyItems): def testCoreTree_Reorder(dummyGUI, dummyItems):
"""Test changing tree order. """Test changing tree order.
@@ -482,6 +488,7 @@ def testCoreTree_Reorder(dummyGUI, dummyItems):
# END Test testCoreTree_Reorder # END Test testCoreTree_Reorder
@pytest.mark.core @pytest.mark.core
def testCoreTree_XMLPackUnpack(dummyGUI, dummyItems): def testCoreTree_XMLPackUnpack(dummyGUI, dummyItems):
"""Test packing and unpacking the tree to and from XML. """Test packing and unpacking the tree to and from XML.
@@ -537,6 +544,7 @@ def testCoreTree_XMLPackUnpack(dummyGUI, dummyItems):
# END Test testCoreTree_XMLPackUnpack # END Test testCoreTree_XMLPackUnpack
@pytest.mark.core @pytest.mark.core
def testCoreTree_ToCFile(monkeypatch, dummyGUI, dummyItems, tmpDir): def testCoreTree_ToCFile(monkeypatch, dummyGUI, dummyItems, tmpDir):
"""Test writing the ToC.txt file. """Test writing the ToC.txt file.
+3 -3
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter About Dialog Class Tester novelWriter About Dialog Class Tester
======================================= =======================================
@@ -32,12 +31,13 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testDlgAbout_Dialog(qtbot, monkeypatch, nwGUI): def testDlgAbout_Dialog(qtbot, monkeypatch, nwGUI):
"""Test the full about dialogs. """Test the full about dialogs.
""" """
# NW About # NW About
monkeypatch.setattr(GuiAbout, "exec_", lambda *args: None) monkeypatch.setattr(GuiAbout, "exec_", lambda *a: None)
nwGUI.mainMenu.aAboutNW.activate(QAction.Trigger) nwGUI.mainMenu.aAboutNW.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiAbout") is not None, timeout=1000) 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 assert msgAbout.tabBox.currentWidget() == msgAbout.pageNotes
# Qt About # Qt About
monkeypatch.setattr(QMessageBox, "aboutQt", lambda *args, **kwargs: None) monkeypatch.setattr(QMessageBox, "aboutQt", lambda *a, **k: None)
nwGUI.mainMenu.aAboutQt.activate(QAction.Trigger) nwGUI.mainMenu.aAboutQt.activate(QAction.Trigger)
# qtbot.stopForInteraction() # qtbot.stopForInteraction()
+3 -3
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Other Dialog Classes Tester novelWriter Other Dialog Classes Tester
========================================= =========================================
@@ -31,12 +30,13 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testDlgOther_QuoteSelect(qtbot, monkeypatch, nwGUI, nwMinimal): def testDlgOther_QuoteSelect(monkeypatch, nwGUI):
"""Test the quote symbols dialog. """Test the quote symbols dialog.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
nwQuot = GuiQuoteSelect(nwGUI) nwQuot = GuiQuoteSelect(nwGUI)
nwQuot.show() nwQuot.show()
+5 -5
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Item Editor Dialog Class Tester novelWriter Item Editor Dialog Class Tester
============================================= =============================================
@@ -36,8 +35,9 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @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. """Test the full item editor dialog.
""" """
projFile = os.path.join(fncProj, "nwProject.nwx") 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") compFile = os.path.join(refDir, "guiItemEditor_Dialog_nwProject.nwx")
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True) monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
# Create new, save, open project # Create new, save, open project
nwGUI.theProject.projTree.setSeed(42) nwGUI.theProject.projTree.setSeed(42)
@@ -54,7 +54,7 @@ def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir,
assert nwGUI.openDocument("0e17daca5f3e1") assert nwGUI.openDocument("0e17daca5f3e1")
assert nwGUI.treeView.setSelectedHandle("0e17daca5f3e1", doScroll=True) 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) nwGUI.mainMenu.aEditItem.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000) qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000)
+2 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Merge and Split Dialog Classes Tester novelWriter Merge and Split Dialog Classes Tester
=================================================== ===================================================
@@ -36,8 +35,9 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj): def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj):
"""Test the merge documents tool. """Test the merge documents tool.
""" """
# Block message box # Block message box
+7 -7
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Preferences Dialog Class Tester novelWriter Preferences Dialog Class Tester
============================================= =============================================
@@ -40,13 +39,14 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir): def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
"""Test the load project wizard. """Test the load project wizard.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
# Must create a clean config and GUI object as the test-wide # 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 # 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 assert theConf.confPath == fncDir
theConf.spellTool = nwConst.SP_INTERNAL theConf.spellTool = nwConst.SP_INTERNAL
monkeypatch.setattr(GuiPreferences, "exec_", lambda *args: None) monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
monkeypatch.setattr(GuiPreferences, "result", lambda *args: QDialog.Accepted) monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
nwGUI.mainMenu.aPreferences.activate(QAction.Trigger) nwGUI.mainMenu.aPreferences.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000) qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000)
@@ -125,9 +125,9 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
# qtbot.stopForInteraction() # qtbot.stopForInteraction()
# Check Browse button # Check Browse button
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "") monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "")
assert not tabProjects._backupFolder() 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.mouseClick(tabProjects.backupGetPath, Qt.LeftButton)
qtbot.wait(keyDelay) qtbot.wait(keyDelay)
+4 -4
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Load Dialog Class Tester novelWriter Project Load Dialog Class Tester
============================================== ==============================================
@@ -37,6 +36,7 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal): def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
"""Test the load project wizard. """Test the load project wizard.
@@ -48,8 +48,8 @@ def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
assert nwGUI.closeProject() assert nwGUI.closeProject()
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *args: None) monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *a: None)
monkeypatch.setattr(GuiProjectLoad, "result", lambda *args: QDialog.Accepted) monkeypatch.setattr(GuiProjectLoad, "result", lambda *a: QDialog.Accepted)
nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger) nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000) 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 assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
getFile = os.path.join(nwMinimal, "nwProject.nwx") 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) qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton)
assert nwLoad.openPath == nwMinimal assert nwLoad.openPath == nwMinimal
assert nwLoad.openState == nwLoad.OPEN_STATE assert nwLoad.openState == nwLoad.OPEN_STATE
+6 -6
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Settings Dialog Class Tester novelWriter Project Settings Dialog Class Tester
================================================== ==================================================
@@ -38,6 +37,7 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDir, refDir): def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDir, refDir):
"""Test the full project settings dialog. """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") compFile = os.path.join(refDir, "guiProjSettings_Dialog_nwProject.nwx")
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
# Check that we cannot open when there is no project # Check that we cannot open when there is no project
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger) 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"}) nwGUI.theProject.setAutoReplace({"A": "B", "C": "D"})
# Get the dialog object # Get the dialog object
monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *args: None) monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *a: None)
monkeypatch.setattr(GuiProjectSettings, "result", lambda *args: QDialog.Accepted) monkeypatch.setattr(GuiProjectSettings, "result", lambda *a: QDialog.Accepted)
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger) nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000) 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 assert projEdit.tabStatus.listBox.topLevelItemCount() == 3
# Add a new item # 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) qtbot.mouseClick(projEdit.tabStatus.addButton, Qt.LeftButton)
projEdit.tabStatus.listBox.topLevelItem(3).setSelected(True) projEdit.tabStatus.listBox.topLevelItem(3).setSelected(True)
for n in range(8): for n in range(8):
+2 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Merge and Split Dialog Classes Tester novelWriter Merge and Split Dialog Classes Tester
=================================================== ===================================================
@@ -37,8 +36,9 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj): def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj):
"""Test the split document tool. """Test the split document tool.
""" """
# Block message box # Block message box
+9 -7
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Other Dialog Classes Tester novelWriter Other Dialog Classes Tester
========================================= =========================================
@@ -21,6 +20,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import os import os
import pytest
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QMessageBox, QAction from PyQt5.QtWidgets import QDialog, QMessageBox, QAction
@@ -35,14 +35,16 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 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. """test the word list editor.
""" """
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiWordList, "exec_", lambda *args: None) monkeypatch.setattr(GuiWordList, "exec_", lambda *a: None)
monkeypatch.setattr(GuiWordList, "result", lambda *args: QDialog.Accepted) monkeypatch.setattr(GuiWordList, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(GuiWordList, "accept", lambda *args: None) monkeypatch.setattr(GuiWordList, "accept", lambda *a: None)
# Open project # Open project
nwGUI.openProject(nwMinimal) nwGUI.openProject(nwMinimal)
+11 -10
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Main GUI Editor Class Tester 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 <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import pytest
import os import os
import pytest
from shutil import copyfile from shutil import copyfile
from tools import cmpFiles from tools import cmpFiles
@@ -39,17 +38,18 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir): def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir):
"""Test the document editor. """Test the document editor.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *args: None) monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: None)
monkeypatch.setattr(GuiItemEditor, "result", lambda *args: QDialog.Accepted) monkeypatch.setattr(GuiItemEditor, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True) monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *args: True) monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True)
# Create new, save, close project # Create new, save, close project
nwGUI.theProject.projTree.setSeed(42) nwGUI.theProject.projTree.setSeed(42)
@@ -353,13 +353,14 @@ def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir):
# END Test testGuiEditor_Main # END Test testGuiEditor_Main
@pytest.mark.gui @pytest.mark.gui
def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum): def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the document editor search functionality. """Test the document editor search functionality.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *args: True) monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True)
nwGUI.theProject.projTree.setSeed(42) nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.openProject(nwLipsum) assert nwGUI.openProject(nwLipsum)
+3 -3
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Main GUI Viewer Class Tester novelWriter Main GUI Viewer Class Tester
========================================== ==========================================
@@ -32,13 +31,14 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum): def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the document viewer. """Test the document viewer.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
# Open project # Open project
nwGUI.theProject.projTree.setSeed(42) nwGUI.theProject.projTree.setSeed(42)
+19 -14
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Main GUI Main Menu Class Tester novelWriter Main GUI Main Menu Class Tester
============================================= =============================================
@@ -35,6 +34,7 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum): def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the main menu Edit and Format entries. """Test the main menu Edit and Format entries.
@@ -113,44 +113,45 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
# Block Formats # Block Formats
# =============
assert nwGUI.docEditor.setCursorPosition(30) assert nwGUI.docEditor.setCursorPosition(30)
## Header 1 # Header 1
nwGUI.mainMenu.aFmtHead1.activate(QAction.Trigger) nwGUI.mainMenu.aFmtHead1.activate(QAction.Trigger)
fmtStr = "# Pellentesque nec erat ut nulla posuere commodo." fmtStr = "# Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:76] == fmtStr assert nwGUI.docEditor.getText()[27:76] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Header 2 # Header 2
nwGUI.mainMenu.aFmtHead2.activate(QAction.Trigger) nwGUI.mainMenu.aFmtHead2.activate(QAction.Trigger)
fmtStr = "## Pellentesque nec erat ut nulla posuere commodo." fmtStr = "## Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:77] == fmtStr assert nwGUI.docEditor.getText()[27:77] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Header 3 # Header 3
nwGUI.mainMenu.aFmtHead3.activate(QAction.Trigger) nwGUI.mainMenu.aFmtHead3.activate(QAction.Trigger)
fmtStr = "### Pellentesque nec erat ut nulla posuere commodo." fmtStr = "### Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:78] == fmtStr assert nwGUI.docEditor.getText()[27:78] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Header 4 # Header 4
nwGUI.mainMenu.aFmtHead4.activate(QAction.Trigger) nwGUI.mainMenu.aFmtHead4.activate(QAction.Trigger)
fmtStr = "#### Pellentesque nec erat ut nulla posuere commodo." fmtStr = "#### Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:79] == fmtStr assert nwGUI.docEditor.getText()[27:79] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Clear Format # Clear Format
nwGUI.mainMenu.aFmtNoFormat.activate(QAction.Trigger) nwGUI.mainMenu.aFmtNoFormat.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[27:74] == cleanText assert nwGUI.docEditor.getText()[27:74] == cleanText
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Comment On # Comment On
nwGUI.mainMenu.aFmtComment.activate(QAction.Trigger) nwGUI.mainMenu.aFmtComment.activate(QAction.Trigger)
fmtStr = "% Pellentesque nec erat ut nulla posuere commodo." fmtStr = "% Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[27:76] == fmtStr assert nwGUI.docEditor.getText()[27:76] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Comment Off # Comment Off
nwGUI.mainMenu.aFmtComment.activate(QAction.Trigger) nwGUI.mainMenu.aFmtComment.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[27:74] == cleanText assert nwGUI.docEditor.getText()[27:74] == cleanText
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
@@ -228,41 +229,43 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
assert nwGUI.docEditor.isEmpty() assert nwGUI.docEditor.isEmpty()
# Alignment & Indent # Alignment & Indent
# ==================
cleanText = "A single, short paragraph.\n\n" cleanText = "A single, short paragraph.\n\n"
nwGUI.docEditor.setText(cleanText) nwGUI.docEditor.setText(cleanText)
assert nwGUI.docEditor.setCursorPosition(0) assert nwGUI.docEditor.setCursorPosition(0)
## Left Align # Left Align
nwGUI.mainMenu.aFmtAlignLeft.activate(QAction.Trigger) nwGUI.mainMenu.aFmtAlignLeft.activate(QAction.Trigger)
fmtStr = "A single, short paragraph. <<" fmtStr = "A single, short paragraph. <<"
assert nwGUI.docEditor.getText()[:29] == fmtStr assert nwGUI.docEditor.getText()[:29] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Right Align # Right Align
nwGUI.mainMenu.aFmtAlignRight.activate(QAction.Trigger) nwGUI.mainMenu.aFmtAlignRight.activate(QAction.Trigger)
fmtStr = ">> A single, short paragraph." fmtStr = ">> A single, short paragraph."
assert nwGUI.docEditor.getText()[:29] == fmtStr assert nwGUI.docEditor.getText()[:29] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Centre Align # Centre Align
nwGUI.mainMenu.aFmtAlignCentre.activate(QAction.Trigger) nwGUI.mainMenu.aFmtAlignCentre.activate(QAction.Trigger)
fmtStr = ">> A single, short paragraph. <<" fmtStr = ">> A single, short paragraph. <<"
assert nwGUI.docEditor.getText()[:32] == fmtStr assert nwGUI.docEditor.getText()[:32] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Left Indent # Left Indent
nwGUI.mainMenu.aFmtIndentLeft.activate(QAction.Trigger) nwGUI.mainMenu.aFmtIndentLeft.activate(QAction.Trigger)
fmtStr = "> A single, short paragraph." fmtStr = "> A single, short paragraph."
assert nwGUI.docEditor.getText()[:28] == fmtStr assert nwGUI.docEditor.getText()[:28] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## Right Indent # Right Indent
nwGUI.mainMenu.aFmtIndentRight.activate(QAction.Trigger) nwGUI.mainMenu.aFmtIndentRight.activate(QAction.Trigger)
fmtStr = "> A single, short paragraph. <" fmtStr = "> A single, short paragraph. <"
assert nwGUI.docEditor.getText()[:30] == fmtStr assert nwGUI.docEditor.getText()[:30] == fmtStr
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
## No Format # No Format
nwGUI.mainMenu.aFmtNoFormat.activate(QAction.Trigger) nwGUI.mainMenu.aFmtNoFormat.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[:30] == cleanText assert nwGUI.docEditor.getText()[:30] == cleanText
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
@@ -368,6 +371,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
# END Test testGuiMenu_EditFormat # END Test testGuiMenu_EditFormat
@pytest.mark.gui @pytest.mark.gui
def testGuiMenu_ContextMenus(qtbot, monkeypatch, nwGUI, nwLipsum): def testGuiMenu_ContextMenus(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the context menus. """Test the context menus.
@@ -452,6 +456,7 @@ def testGuiMenu_ContextMenus(qtbot, monkeypatch, nwGUI, nwLipsum):
# END Test testGuiMenu_ContextMenus # END Test testGuiMenu_ContextMenus
@pytest.mark.gui @pytest.mark.gui
def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj): def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
"""Test the Insert menu. """Test the Insert menu.
+4 -4
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Main GUI Novel Tree Class Tester novelWriter Main GUI Novel Tree Class Tester
============================================== ==============================================
@@ -28,13 +27,14 @@ from tools import writeFile
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
@pytest.mark.gui @pytest.mark.gui
def testGuiNovelTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal): def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
"""Test navigating the novel tree. """Test navigating the novel tree.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
nwGUI.openProject(nwMinimal) nwGUI.openProject(nwMinimal)
nwGUI.theProject.projTree.setSeed(42) nwGUI.theProject.projTree.setSeed(42)
+3 -3
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Main GUI Outline Class Tester novelWriter Main GUI Outline Class Tester
=========================================== ===========================================
@@ -31,13 +30,14 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum): def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the outline view. """Test the outline view.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
assert nwGUI.openProject(nwLipsum) assert nwGUI.openProject(nwLipsum)
nwGUI.mainConf.lastPath = nwLipsum nwGUI.mainConf.lastPath = nwLipsum
+5 -5
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Project Details Dialog Class Tester novelWriter Project Details Dialog Class Tester
================================================= =================================================
@@ -32,15 +31,16 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testGuiProjDetails_Dialog(qtbot, monkeypatch, nwGUI, nwLipsum): def testGuiProjDetails_Dialog(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the project details dialog. """Test the project details dialog.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
# Create a project to work on # Create a project to work on
assert nwGUI.openProject(nwLipsum) assert nwGUI.openProject(nwLipsum)
+9 -9
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Main GUI Project Tree Class Tester novelWriter Main GUI Project Tree Class Tester
================================================ ================================================
@@ -32,16 +31,17 @@ from nw.guimain import GuiMain
from nw.gui.projtree import GuiProjectTree from nw.gui.projtree import GuiProjectTree
from nw.enum import nwItemType, nwItemClass from nw.enum import nwItemType, nwItemClass
@pytest.mark.gui @pytest.mark.gui
def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal): def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
"""Test adding and removing items from the project tree. """Test adding and removing items from the project tree.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiMain, "editItem", lambda *args: None) monkeypatch.setattr(GuiMain, "editItem", lambda *a: None)
nwGUI.theProject.projTree.setSeed(42) nwGUI.theProject.projTree.setSeed(42)
nwTree = nwGUI.treeView nwTree = nwGUI.treeView
@@ -98,12 +98,12 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
nwTree.setSelectedHandle("8c659a11cd429") nwTree.setSelectedHandle("8c659a11cd429")
# Shift focus and try to move item # 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 not nwTree.moveTreeItem(1)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "44cb730c42048", "71ee45a3c0db9" "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) # Move second item up twice (should give same result)
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger) nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
@@ -228,7 +228,7 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
nwTree.clearSelection() nwTree.clearSelection()
# Add a file with no parent, and fail to find a suitable parent item # 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.FILE, nwItemClass.NOVEL)
assert not nwTree.newTreeItem(nwItemType.FOLDER, nwItemClass.NOVEL) assert not nwTree.newTreeItem(nwItemType.FOLDER, nwItemClass.NOVEL)
+2 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter GUI Theme and Icons Classes Tester novelWriter GUI Theme and Icons Classes Tester
================================================ ================================================
@@ -30,12 +29,13 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir): def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir):
"""Test the theme and icon classes. """Test the theme and icon classes.
""" """
# Block message box # 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]) nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % tmpDir, nwMinimal])
qtbot.addWidget(nwGUI) qtbot.addWidget(nwGUI)
+6 -6
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Build Dialog Class Tester novelWriter Build Dialog Class Tester
======================================= =======================================
@@ -35,14 +34,15 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir): def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
"""Test the build tool. """Test the build tool.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda a, b, c, **kwargs: (c, None)) monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda a, b, c, **k: (c, None))
# Check that we cannot open when there is no project # Check that we cannot open when there is no project
nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger) nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger)
@@ -69,7 +69,7 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
# Non-existent path # Non-existent path
with monkeypatch.context() as mp: 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 assert nwGUI.mainConf.lastPath != nwLipsum
nwGUI.mainConf.lastPath = "no_such_path" nwGUI.mainConf.lastPath = "no_such_path"
assert nwBuild._saveDocument(nwBuild.FMT_NWD) assert nwBuild._saveDocument(nwBuild.FMT_NWD)
@@ -77,7 +77,7 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
# No path selected # No path selected
with monkeypatch.context() as mp: 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) assert not nwBuild._saveDocument(nwBuild.FMT_NWD)
# Default Settings # Default Settings
+7 -7
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter New Project Wizard Class Tester novelWriter New Project Wizard Class Tester
============================================= =============================================
@@ -39,13 +38,14 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testToolProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal): def testToolProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
"""Test the new project wizard. """Test the new project wizard.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
if sys.platform.startswith("darwin"): if sys.platform.startswith("darwin"):
# Disable for macOS because the test segfaults on QWizard.show() # 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 # Close project, but call with invalid path
assert nwGUI.closeProject() assert nwGUI.closeProject()
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(nwGUI, "showNewProjectDialog", lambda *args: None) mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: None)
assert not nwGUI.newProject() assert not nwGUI.newProject()
# Now, with an empty dictionary # Now, with an empty dictionary
mp.setattr(nwGUI, "showNewProjectDialog", lambda *args: {}) mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {})
assert not nwGUI.newProject() assert not nwGUI.newProject()
# Now, with a non-empty folder # 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() assert not nwGUI.newProject()
## ##
# Test the Wizard # Test the Wizard
## ##
monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *args: None) monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *a: None)
nwGUI.mainConf.lastPath = " " nwGUI.mainConf.lastPath = " "
nwGUI.closeProject() nwGUI.closeProject()
+7 -7
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Writing Stats Dialog Class Tester novelWriter Writing Stats Dialog Class Tester
=============================================== ===============================================
@@ -37,15 +36,16 @@ keyDelay = 2
typeDelay = 1 typeDelay = 1
stepDelay = 20 stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj): def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
"""Test the full writing stats tool. """Test the full writing stats tool.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
# Create a project to work on # Create a project to work on
assert nwGUI.newProject({"projPath": fncProj}) assert nwGUI.newProject({"projPath": fncProj})
@@ -116,13 +116,13 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
sessLog.populateGUI() sessLog.populateGUI()
# Make the saving fail # 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_CSV)
assert not sessLog._saveData(sessLog.FMT_JSON) assert not sessLog._saveData(sessLog.FMT_JSON)
assert not sessLog._saveData(None) assert not sessLog._saveData(None)
# Make the save succeed # 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, "")) monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda ss, tt, pp, options: (pp, ""))
sessLog.listBox.sortByColumn(sessLog.C_TIME, 0) sessLog.listBox.sortByColumn(sessLog.C_TIME, 0)
+5 -1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
novelWriter Test Suite Tools novelWriter Test Suite Tools
============================== ==============================
@@ -25,6 +24,7 @@ import shutil
from PyQt5.QtWidgets import qApp from PyQt5.QtWidgets import qApp
def cmpFiles(fileOne, fileTwo, ignoreLines=None): def cmpFiles(fileOne, fileTwo, ignoreLines=None):
"""Compare two files, but optionally ignore lines given by a list. """Compare two files, but optionally ignore lines given by a list.
""" """
@@ -70,6 +70,7 @@ def cmpFiles(fileOne, fileTwo, ignoreLines=None):
return not diffFound return not diffFound
def getGuiItem(theName): def getGuiItem(theName):
"""Returns a QtWidget based on its objectName. """Returns a QtWidget based on its objectName.
""" """
@@ -78,18 +79,21 @@ def getGuiItem(theName):
return qWidget return qWidget
return None return None
def readFile(fileName): def readFile(fileName):
"""Returns the content of a file as a string. """Returns the content of a file as a string.
""" """
with open(fileName, mode="r", encoding="utf8") as inFile: with open(fileName, mode="r", encoding="utf8") as inFile:
return inFile.read() return inFile.read()
def writeFile(fileName, fileData): def writeFile(fileName, fileData):
"""Write the contents of a string to a file. """Write the contents of a string to a file.
""" """
with open(fileName, mode="w", encoding="utf8") as outFile: with open(fileName, mode="w", encoding="utf8") as outFile:
outFile.write(fileData) outFile.write(fileData)
def cleanProject(projPath): def cleanProject(projPath):
"""Delete all generated files in a project. """Delete all generated files in a project.
""" """