Fix various issues in the code (#1197)

This commit is contained in:
Veronica Berglyd Olsen
2022-10-20 12:30:00 +02:00
committed by GitHub
20 changed files with 241 additions and 268 deletions
+99 -127
View File
@@ -216,25 +216,25 @@ def formatInt(value):
return str(value) return str(value)
def formatTimeStamp(theTime, fileSafe=False): def formatTimeStamp(value, 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.
""" """
if fileSafe: if fileSafe:
return datetime.fromtimestamp(theTime).strftime(nwConst.FMT_FSTAMP) return datetime.fromtimestamp(value).strftime(nwConst.FMT_FSTAMP)
else: else:
return datetime.fromtimestamp(theTime).strftime(nwConst.FMT_TSTAMP) return datetime.fromtimestamp(value).strftime(nwConst.FMT_TSTAMP)
def formatTime(tS): def formatTime(t):
"""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.
""" """
if isinstance(tS, int): if isinstance(t, int):
if tS >= 86400: if t >= 86400:
return f"{tS//86400:d}-{tS%86400//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}" return f"{t//86400:d}-{t%86400//3600:02d}:{t%3600//60:02d}:{t%60:02d}"
else: else:
return f"{tS//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}" return f"{t//3600:02d}:{t%3600//60:02d}:{t%60:02d}"
return "ERROR" return "ERROR"
@@ -276,111 +276,111 @@ def splitVersionNumber(value):
return vMajor, vMinor, vPatch, vInt return vMajor, vMinor, vPatch, vInt
def transferCase(theSource, theTarget): def transferCase(source, target):
"""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.
""" """
theResult = theTarget theResult = target
if not isinstance(theSource, str) or not isinstance(theTarget, str): if not isinstance(source, str) or not isinstance(target, str):
return theResult return theResult
if len(theTarget) < 1 or len(theSource) < 1: if len(target) < 1 or len(source) < 1:
return theResult return theResult
if theSource.istitle(): if source.istitle():
theResult = theTarget.title() theResult = target.title()
if theSource.isupper(): if source.isupper():
theResult = theTarget.upper() theResult = target.upper()
elif theSource.islower(): elif source.islower():
theResult = theTarget.lower() theResult = target.lower()
return theResult return theResult
def fuzzyTime(secDiff): def fuzzyTime(seconds):
"""Converts a time difference in seconds into a fuzzy time string. """Converts a time difference in seconds into a fuzzy time string.
""" """
if secDiff < 0: if seconds < 0:
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "in the future" "Common", "in the future"
) )
elif secDiff < 30: elif seconds < 30:
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "just now" "Common", "just now"
) )
elif secDiff < 90: elif seconds < 90:
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "a minute ago" "Common", "a minute ago"
) )
elif secDiff < 3300: # 55 minutes elif seconds < 3300: # 55 minutes
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "{0} minutes ago" "Common", "{0} minutes ago"
).format(int(round(secDiff/60))) ).format(int(round(seconds/60)))
elif secDiff < 5400: # 90 minutes elif seconds < 5400: # 90 minutes
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "an hour ago" "Common", "an hour ago"
) )
elif secDiff < 84600: # 23.5 hours elif seconds < 84600: # 23.5 hours
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "{0} hours ago" "Common", "{0} hours ago"
).format(int(round(secDiff/3600))) ).format(int(round(seconds/3600)))
elif secDiff < 129600: # 1.5 days elif seconds < 129600: # 1.5 days
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "a day ago" "Common", "a day ago"
) )
elif secDiff < 561600: # 6.5 days elif seconds < 561600: # 6.5 days
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "{0} days ago" "Common", "{0} days ago"
).format(int(round(secDiff/86400))) ).format(int(round(seconds/86400)))
elif secDiff < 907200: # 10.5 days elif seconds < 907200: # 10.5 days
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "a week ago" "Common", "a week ago"
) )
elif secDiff < 2419200: # 28 days elif seconds < 2419200: # 28 days
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "{0} weeks ago" "Common", "{0} weeks ago"
).format(int(round(secDiff/604800))) ).format(int(round(seconds/604800)))
elif secDiff < 3888000: # 45 days elif seconds < 3888000: # 45 days
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "a month ago" "Common", "a month ago"
) )
elif secDiff < 29808000: # 345 days elif seconds < 29808000: # 345 days
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "{0} months ago" "Common", "{0} months ago"
).format(int(round(secDiff/2592000))) ).format(int(round(seconds/2592000)))
elif secDiff < 47336400: # 1.5 years elif seconds < 47336400: # 1.5 years
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "a year ago" "Common", "a year ago"
) )
else: else:
return QCoreApplication.translate( return QCoreApplication.translate(
"Common", "{0} years ago" "Common", "{0} years ago"
).format(int(round(secDiff/31557600))) ).format(int(round(seconds/31557600)))
def numberToRoman(numVal, toLower=False): def numberToRoman(value, toLower=False):
"""Convert an integer to a Roman number. """Convert an integer to a Roman number.
""" """
if not isinstance(numVal, int): if not isinstance(value, int):
return "NAN" return "NAN"
if numVal < 1 or numVal > 4999: if value < 1 or value > 4999:
return "OOR" return "OOR"
theValues = [ lookup = [
(1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"), (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"),
(50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I"), (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I"),
] ]
romNum = "" roman = ""
for theDiv, theSym in theValues: for divisor, symbol in lookup:
n = numVal//theDiv n = value//divisor
romNum += n*theSym roman += n*symbol
numVal -= n*theDiv value -= n*divisor
if numVal <= 0: if value <= 0:
break break
return romNum.lower() if toLower else romNum return roman.lower() if toLower else roman
# =============================================================================================== # # =============================================================================================== #
@@ -438,70 +438,70 @@ def jsonEncode(data, n=0, nmax=0):
# File and File System Functions # File and File System Functions
# =============================================================================================== # # =============================================================================================== #
def readTextFile(filePath): def readTextFile(path):
"""Read the content of a text file in a robust manner. """Read the content of a text file in a robust manner.
""" """
if not os.path.isfile(filePath): if not os.path.isfile(path):
return "" return ""
fileText = "" text = ""
try: try:
with open(filePath, mode="r", encoding="utf-8") as inFile: with open(path, mode="r", encoding="utf-8") as inFile:
fileText = inFile.read() text = inFile.read()
except Exception: except Exception:
logger.error("Could not read file: %s", filePath) logger.error("Could not read file: %s", path)
logException() logException()
return "" return ""
return fileText return text
def makeFileNameSafe(value): def makeFileNameSafe(value):
"""Returns a filename safe string of the value. """Returns a filename safe string of the value.
""" """
cleanName = "" clean = ""
for c in str(value).strip(): for c in str(value).strip():
if c.isalpha() or c.isdigit() or c == " ": if c.isalpha() or c.isdigit() or c == " ":
cleanName += c clean += c
return cleanName return clean
def ensureFolder(dirPath, parentPath=None, errLog=None): def ensureFolder(path, parent=None, errLog=None):
"""Make sure a folder exists, and if it doesn't, create it. """Make sure a folder exists, and if it doesn't, create it.
""" """
try: try:
if parentPath: if parent:
dirPath = os.path.join(parentPath, dirPath) path = os.path.join(parent, path)
if not os.path.isdir(dirPath): if not os.path.isdir(path):
os.mkdir(dirPath) os.mkdir(path)
except Exception as exc: except Exception as exc:
logger.error("Could not create folder: %s", dirPath) logger.error("Could not create folder: %s", path)
logException() logException()
if isinstance(errLog, list): if isinstance(errLog, list):
errLog.append(f"Could not create folder: {dirPath}") errLog.append(f"Could not create folder: {path}")
errLog.append(formatException(exc)) errLog.append(formatException(exc))
return False return False
return True return True
def sha256sum(filePath): def sha256sum(path):
"""Make a shasum of a file using a buffer. """Make a shasum of a file using a buffer.
Based on: https://stackoverflow.com/a/44873382/5825851 Based on: https://stackoverflow.com/a/44873382/5825851
""" """
hDigest = hashlib.sha256() digest = hashlib.sha256()
bData = bytearray(65536) bData = bytearray(65536)
mData = memoryview(bData) mData = memoryview(bData)
try: try:
with open(filePath, mode="rb", buffering=0) as inFile: with open(path, mode="rb", buffering=0) as inFile:
for n in iter(lambda: inFile.readinto(mData), 0): for n in iter(lambda: inFile.readinto(mData), 0):
hDigest.update(mData[:n]) digest.update(mData[:n])
except Exception: except Exception:
logger.error("Could not create sha256sum of: %s", filePath) logger.error("Could not create sha256sum of: %s", path)
logException() logException()
return None return None
return hDigest.hexdigest() return digest.hexdigest()
# =============================================================================================== # # =============================================================================================== #
@@ -523,87 +523,59 @@ def getGuiItem(objName):
class NWConfigParser(ConfigParser): class NWConfigParser(ConfigParser):
CNF_STR = 0
CNF_INT = 1
CNF_FLOAT = 2
CNF_BOOL = 3
CNF_S_LST = 4
CNF_I_LST = 5
def __init__(self): def __init__(self):
super().__init__() super().__init__()
def rdStr(self, section, option, default): def rdStr(self, section, option, default):
"""Read string value. """Read string value.
""" """
return self._parseLine(section, option, default, self.CNF_STR) return self.get(section, option, fallback=default)
def rdInt(self, section, option, default): def rdInt(self, section, option, default):
"""Read integer value. """Read integer value.
""" """
return self._parseLine(section, option, default, self.CNF_INT) try:
return self.getint(section, option, fallback=default)
except ValueError:
logger.error("Could not read '%s':'%s' from config", section, option)
return default
def rdFlt(self, section, option, default): def rdFlt(self, section, option, default):
"""Read float value. """Read float value.
""" """
return self._parseLine(section, option, default, self.CNF_FLOAT) try:
return self.getfloat(section, option, fallback=default)
except ValueError:
logger.error("Could not read '%s':'%s' from config", section, option)
return default
def rdBool(self, section, option, default): def rdBool(self, section, option, default):
"""Read boolean value. """Read boolean value.
""" """
return self._parseLine(section, option, default, self.CNF_BOOL) try:
return self.getboolean(section, option, fallback=default)
except ValueError:
logger.error("Could not read '%s':'%s' from config", section, option)
return default
def rdStrList(self, section, option, default): def rdStrList(self, section, option, default):
"""Read string list. """Read string list.
""" """
return self._parseLine(section, option, default, self.CNF_S_LST) result = default.copy() if isinstance(default, list) else []
if self.has_option(section, option):
data = self.get(section, option, fallback="").split(",")
for i in range(min(len(data), len(result))):
result[i] = data[i].strip()
return result
def rdIntList(self, section, option, default): def rdIntList(self, section, option, default):
"""Read integer list. """Read integer list.
""" """
return self._parseLine(section, option, default, self.CNF_I_LST) result = default.copy() if isinstance(default, list) else []
##
# Internal Functions
##
def _unpackList(self, value, default, type):
"""Unpack a comma-separated string of items into a list.
"""
inList = value.split(",")
outList = []
if isinstance(default, list):
outList = default.copy()
for i in range(min(len(inList), len(outList))):
try:
if type == self.CNF_S_LST:
outList[i] = inList[i].strip()
elif type == self.CNF_I_LST:
outList[i] = int(inList[i].strip())
except Exception:
continue
return outList
def _parseLine(self, section, option, default, type):
"""Parse a line and return the correct datatype.
"""
if self.has_option(section, option): if self.has_option(section, option):
try: data = self.get(section, option, fallback="").split(",")
if type == self.CNF_STR: for i in range(min(len(data), len(result))):
return self.get(section, option) result[i] = checkInt(data[i].strip(), result[i])
elif type == self.CNF_INT: return result
return self.getint(section, option)
elif type == self.CNF_FLOAT:
return self.getfloat(section, option)
elif type == self.CNF_BOOL:
return self.getboolean(section, option)
elif type in (self.CNF_I_LST, self.CNF_S_LST):
return self._unpackList(self.get(section, option), default, type)
except ValueError:
logger.error("Could not read '%s':'%s' from config", str(section), str(option))
logException()
return default
return default
# END Class NWConfigParser # END Class NWConfigParser
+6 -8
View File
@@ -52,12 +52,11 @@ class Config:
# Set Application Variables # Set Application Variables
self.appName = "novelWriter" self.appName = "novelWriter"
self.appHandle = self.appName.lower() self.appHandle = "novelwriter"
# Set Paths # Set Paths
self.cmdOpen = None # Path from command line for project to be opened on launch self.cmdOpen = None # Path from command line for project to be opened on launch
self.confPath = None # Folder where the config is saved self.confPath = None # Folder where the config is saved
self.confFile = None # The config file name
self.dataPath = None # Folder where app data is stored self.dataPath = None # Folder where app data is stored
self.lastPath = None # The last user-selected folder (browse dialogs) self.lastPath = None # The last user-selected folder (browse dialogs)
self.appPath = None # The full path to the novelwriter package folder self.appPath = None # The full path to the novelwriter package folder
@@ -271,7 +270,6 @@ class Config:
logger.debug("Config path: %s", self.confPath) logger.debug("Config path: %s", self.confPath)
logger.debug("Data path: %s", self.dataPath) logger.debug("Data path: %s", self.dataPath)
self.confFile = self.appHandle+".conf"
self.lastPath = os.path.expanduser("~") self.lastPath = os.path.expanduser("~")
self.appPath = getattr(sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__))) self.appPath = getattr(sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__)))
self.appRoot = os.path.abspath(os.path.join(self.appPath, os.path.pardir)) self.appRoot = os.path.abspath(os.path.join(self.appPath, os.path.pardir))
@@ -306,12 +304,12 @@ class Config:
# We don't error on these failing since they are not essential # We don't error on these failing since they are not essential
if self.dataPath is not None: if self.dataPath is not None:
ensureFolder("syntax", parentPath=self.dataPath) ensureFolder("syntax", parent=self.dataPath)
ensureFolder("themes", parentPath=self.dataPath) ensureFolder("themes", parent=self.dataPath)
# Check if config file exists # Check if config file exists
if self.confPath is not None: if self.confPath is not None:
if os.path.isfile(os.path.join(self.confPath, self.confFile)): if os.path.isfile(os.path.join(self.confPath, nwFiles.CONF_FILE)):
# If it exists, load it # If it exists, load it
self.loadConfig() self.loadConfig()
else: else:
@@ -396,7 +394,7 @@ class Config:
return False return False
theConf = NWConfigParser() theConf = NWConfigParser()
cnfPath = os.path.join(self.confPath, self.confFile) cnfPath = os.path.join(self.confPath, nwFiles.CONF_FILE)
try: try:
with open(cnfPath, mode="r", encoding="utf-8") as inFile: with open(cnfPath, mode="r", encoding="utf-8") as inFile:
theConf.read_file(inFile) theConf.read_file(inFile)
@@ -619,7 +617,7 @@ class Config:
} }
# Write config file # Write config file
cnfPath = os.path.join(self.confPath, self.confFile) cnfPath = os.path.join(self.confPath, nwFiles.CONF_FILE)
try: try:
with open(cnfPath, mode="w", encoding="utf-8") as outFile: with open(cnfPath, mode="w", encoding="utf-8") as outFile:
theConf.write(outFile) theConf.write(outFile)
+1
View File
@@ -68,6 +68,7 @@ class nwHeaders:
class nwFiles: class nwFiles:
CONF_FILE = "novelwriter.conf"
PROJ_FILE = "nwProject.nwx" PROJ_FILE = "nwProject.nwx"
PROJ_DICT = "wordlist.txt" PROJ_DICT = "wordlist.txt"
PROJ_LOCK = "nwProject.lock" PROJ_LOCK = "nwProject.lock"
+5 -7
View File
@@ -85,7 +85,6 @@ class NWProject:
self.projDict = None # The spell check dictionary self.projDict = None # The spell check dictionary
self.projSpell = None # The spell check language, if different than default self.projSpell = None # The spell check language, if different than default
self.projLang = None # The project language, used for builds self.projLang = None # The project language, used for builds
self.projFile = None # The file name of the project main XML file
self.projFiles = [] # A list of all files in the content folder on load self.projFiles = [] # A list of all files in the content folder on load
# Project Meta # Project Meta
@@ -260,7 +259,6 @@ class NWProject:
self.projDict = None self.projDict = None
self.projSpell = None self.projSpell = None
self.projLang = None self.projLang = None
self.projFile = nwFiles.PROJ_FILE
self.projFiles = [] self.projFiles = []
self.projName = "" self.projName = ""
self.bookTitle = "" self.bookTitle = ""
@@ -774,9 +772,9 @@ class NWProject:
self._projTree.packXML(nwXML) self._projTree.packXML(nwXML)
# Write the xml tree to file # Write the xml tree to file
tempFile = os.path.join(self.projPath, self.projFile+"~") tempFile = os.path.join(self.projPath, nwFiles.PROJ_FILE+"~")
saveFile = os.path.join(self.projPath, self.projFile) saveFile = os.path.join(self.projPath, nwFiles.PROJ_FILE)
backFile = os.path.join(self.projPath, self.projFile[:-3]+"bak") backFile = os.path.join(self.projPath, nwFiles.PROJ_FILE[:-3]+"bak")
try: try:
with open(tempFile, mode="wb") as outFile: with open(tempFile, mode="wb") as outFile:
outFile.write(etree.tostring( outFile.write(etree.tostring(
@@ -816,7 +814,7 @@ class NWProject:
return True return True
def closeProject(self, idleTime=0): def closeProject(self, idleTime=0.0):
"""Close the current project and clear all meta data. """Close the current project and clear all meta data.
""" """
logger.info("Closing project: %s", self.projPath) logger.info("Closing project: %s", self.projPath)
@@ -1185,7 +1183,7 @@ class NWProject:
information to the GUI statusbar. information to the GUI statusbar.
""" """
self.projChanged = bValue self.projChanged = bValue
self.mainGui.statusBar.doUpdateProjectStatus(bValue) self.mainGui.mainStatus.doUpdateProjectStatus(bValue)
if bValue: if bValue:
# If we've changed the project at all, this should be True # If we've changed the project at all, this should be True
self.projAltered = True self.projAltered = True
+1 -1
View File
@@ -117,7 +117,7 @@ class GuiDocMerge(QDialog):
finalItems = [] finalItems = []
for i in range(self.listBox.count()): for i in range(self.listBox.count()):
item = self.listBox.item(i) item = self.listBox.item(i)
if item.checkState() == Qt.Checked: if item is not None and item.checkState() == Qt.Checked:
finalItems.append(item.data(Qt.UserRole)) finalItems.append(item.data(Qt.UserRole))
self._data["moveToTrash"] = self.trashSwitch.isChecked() self._data["moveToTrash"] = self.trashSwitch.isChecked()
+6 -3
View File
@@ -145,9 +145,12 @@ class GuiDocSplit(QDialog):
headerList = [] headerList = []
for i in range(self.listBox.count()): for i in range(self.listBox.count()):
item = self.listBox.item(i) item = self.listBox.item(i)
headerList.append( if item is not None:
(item.data(self.LINE_ROLE), item.data(self.LEVEL_ROLE), item.data(self.LABEL_ROLE)) headerList.append((
) item.data(self.LINE_ROLE),
item.data(self.LEVEL_ROLE),
item.data(self.LABEL_ROLE),
))
spLevel = self.splitLevel.currentData() spLevel = self.splitLevel.currentData()
intoFolder = self.folderSwitch.isChecked() intoFolder = self.folderSwitch.isChecked()
+13 -10
View File
@@ -365,11 +365,12 @@ class GuiProjectEditStatus(QWidget):
newList = [] newList = []
for n in range(self.listBox.topLevelItemCount()): for n in range(self.listBox.topLevelItemCount()):
item = self.listBox.topLevelItem(n) item = self.listBox.topLevelItem(n)
newList.append({ if item is not None:
"key": item.data(self.COL_LABEL, self.KEY_ROLE), newList.append({
"name": item.text(self.COL_LABEL), "key": item.data(self.COL_LABEL, self.KEY_ROLE),
"cols": item.data(self.COL_LABEL, self.COL_ROLE), "name": item.text(self.COL_LABEL),
}) "cols": item.data(self.COL_LABEL, self.COL_ROLE),
})
return newList, self.colDeleted return newList, self.colDeleted
return [], [] return [], []
@@ -468,7 +469,8 @@ class GuiProjectEditStatus(QWidget):
self.listBox.insertTopLevelItem(nIndex, cItem) self.listBox.insertTopLevelItem(nIndex, cItem)
self.listBox.clearSelection() self.listBox.clearSelection()
cItem.setSelected(True) if cItem is not None:
cItem.setSelected(True)
self.colChanged = True self.colChanged = True
return return
@@ -617,10 +619,11 @@ class GuiProjectEditReplace(QWidget):
newList = {} newList = {}
for n in range(self.listBox.topLevelItemCount()): for n in range(self.listBox.topLevelItemCount()):
tItem = self.listBox.topLevelItem(n) tItem = self.listBox.topLevelItem(n)
aKey = self._stripNotAllowed(tItem.text(0)) if tItem is not None:
aVal = tItem.text(1) aKey = self._stripNotAllowed(tItem.text(0))
if len(aKey) > 0: aVal = tItem.text(1)
newList[aKey] = aVal if len(aKey) > 0:
newList[aKey] = aVal
return newList return newList
+1 -1
View File
@@ -135,7 +135,7 @@ class GuiUpdates(QDialog):
logException() logException()
relVersion = rawData.get("tag_name", "Unknown") relVersion = rawData.get("tag_name", "Unknown")
relDate = rawData.get("created_at", None) relDate = rawData.get("created_at", "")
try: try:
relDate = datetime.strptime(relDate[:10], "%Y-%m-%d").strftime("%x") relDate = datetime.strptime(relDate[:10], "%Y-%m-%d").strftime("%x")
+3 -1
View File
@@ -156,7 +156,9 @@ class GuiWordList(QDialog):
try: try:
with open(tmpFile, mode="w", encoding="utf-8") as outFile: with open(tmpFile, mode="w", encoding="utf-8") as outFile:
for i in range(self.listBox.count()): for i in range(self.listBox.count()):
outFile.write(self.listBox.item(i).text() + "\n") item = self.listBox.item(i)
if item is not None:
outFile.write(item.text() + "\n")
except Exception: except Exception:
logger.error("Could not save new word list") logger.error("Could not save new word list")
+2 -2
View File
@@ -199,8 +199,8 @@ def exceptionHandler(exType, exValue, exTrace):
try: try:
# Try a controlled shutdown # Try a controlled shutdown
nwGUI.closeProject(isYes=True) nwGUI.closeProject(isYes=True) # type: ignore
nwGUI.closeMain() nwGUI.closeMain() # type: ignore
logger.info("Emergency shutdown successful") logger.info("Emergency shutdown successful")
except Exception as exc: except Exception as exc:
+6 -15
View File
@@ -513,7 +513,7 @@ class GuiDocEditor(QTextEdit):
newHeader = self._nwItem.mainHeading newHeader = self._nwItem.mainHeading
# ToDo: This should be a signal # ToDo: This should be a signal
if self._updateHeaders(checkLevel=True): if self._updateHeaders():
self.mainGui.requestNovelTreeRefresh() self.mainGui.requestNovelTreeRefresh()
else: else:
self.mainGui.novelView.updateWordCounts(tHandle) self.mainGui.novelView.updateWordCounts(tHandle)
@@ -740,7 +740,7 @@ class GuiDocEditor(QTextEdit):
qApp.restoreOverrideCursor() qApp.restoreOverrideCursor()
afTime = time() afTime = time()
logger.debug("Document highlighted in %.3f ms", 1000*(afTime-bfTime)) logger.debug("Document highlighted in %.3f ms", 1000*(afTime-bfTime))
self.mainGui.statusBar.setStatus(self.tr("Spell check complete")) self.mainGui.mainStatus.setStatus(self.tr("Spell check complete"))
return True return True
@@ -2025,7 +2025,7 @@ class GuiDocEditor(QTextEdit):
return False return False
return True return True
def _updateHeaders(self, checkPos=False, checkLevel=False): def _updateHeaders(self):
"""Update the headers record and return True if anything """Update the headers record and return True if anything
changed, if a check flag was provided. changed, if a check flag was provided.
""" """
@@ -2033,21 +2033,12 @@ class GuiDocEditor(QTextEdit):
return False return False
newHeaders = self.theProject.index.getHandleHeaders(self._docHandle) newHeaders = self.theProject.index.getHandleHeaders(self._docHandle)
if checkPos: newLev = [x[1] for x in newHeaders]
newPos = [x[0] for x in newHeaders] oldLev = [x[1] for x in self._docHeaders]
oldPos = [x[0] for x in self._docHeaders]
if checkLevel:
newLev = [x[1] for x in newHeaders]
oldLev = [x[1] for x in self._docHeaders]
self._docHeaders = newHeaders self._docHeaders = newHeaders
if checkPos: return newLev != oldLev
return newPos != oldPos
if checkLevel:
return newLev != oldLev
return False
def _checkDocSize(self, theSize): def _checkDocSize(self, theSize):
"""Check if document size crosses the big document limit set in """Check if document size crosses the big document limit set in
+11 -10
View File
@@ -508,16 +508,17 @@ class GuiNovelTree(QTreeWidget):
self._actHandle = tHandle self._actHandle = tHandle
for i in range(self.topLevelItemCount()): for i in range(self.topLevelItemCount()):
tItem = self.topLevelItem(i) tItem = self.topLevelItem(i)
if tItem.data(self.C_TITLE, self.D_HANDLE) == tHandle: if tItem is not None:
tItem.setBackground(self.C_TITLE, self.palette().alternateBase()) if tItem.data(self.C_TITLE, self.D_HANDLE) == tHandle:
tItem.setBackground(self.C_WORDS, self.palette().alternateBase()) tItem.setBackground(self.C_TITLE, self.palette().alternateBase())
tItem.setBackground(self.C_EXTRA, self.palette().alternateBase()) tItem.setBackground(self.C_WORDS, self.palette().alternateBase())
tItem.setBackground(self.C_MORE, self.palette().alternateBase()) tItem.setBackground(self.C_EXTRA, self.palette().alternateBase())
else: tItem.setBackground(self.C_MORE, self.palette().alternateBase())
tItem.setBackground(self.C_TITLE, self.palette().base()) else:
tItem.setBackground(self.C_WORDS, self.palette().base()) tItem.setBackground(self.C_TITLE, self.palette().base())
tItem.setBackground(self.C_EXTRA, self.palette().base()) tItem.setBackground(self.C_WORDS, self.palette().base())
tItem.setBackground(self.C_MORE, self.palette().base()) tItem.setBackground(self.C_EXTRA, self.palette().base())
tItem.setBackground(self.C_MORE, self.palette().base())
logger.debug("Highlighted Novel Tree in %.3f ms", (time() - tStart)*1000) logger.debug("Highlighted Novel Tree in %.3f ms", (time() - tStart)*1000)
+4 -3
View File
@@ -675,9 +675,10 @@ class GuiOutlineTree(QTreeWidget):
self.setColumnHidden(self._colIdx[nwOutline.TITLE], False) self.setColumnHidden(self._colIdx[nwOutline.TITLE], False)
headItem = self.headerItem() headItem = self.headerItem()
headItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignRight) if headItem is not None:
headItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight) headItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignRight)
headItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight) headItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight)
headItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight)
novStruct = self.theProject.index.novelStructure(rootHandle=rootHandle, skipExcl=True) novStruct = self.theProject.index.novelStructure(rootHandle=rootHandle, skipExcl=True)
for _, tHandle, sTitle, novIdx in novStruct: for _, tHandle, sTitle, novIdx in novStruct:
+4 -3
View File
@@ -1211,13 +1211,13 @@ class GuiProjectTree(QTreeWidget):
if hasChild and isFolder: if hasChild and isFolder:
mTrans.addAction( mTrans.addAction(
self.tr("Combine Documents in Folder"), self.tr("Merge Documents in Folder"),
lambda: self._mergeDocuments(tHandle, True) lambda: self._mergeDocuments(tHandle, True)
) )
if isFile: if isFile:
mTrans.addAction( mTrans.addAction(
self.tr("Split Document by Header"), self.tr("Split Document by Headers"),
lambda: self._splitDocument(tHandle) lambda: self._splitDocument(tHandle)
) )
@@ -1309,7 +1309,8 @@ class GuiProjectTree(QTreeWidget):
self._postItemMove(sHandle, wCount) self._postItemMove(sHandle, wCount)
self._recordLastMove(sItem, pItem, pIndex) self._recordLastMove(sItem, pItem, pIndex)
self._alertTreeChange(sHandle, flush=True) self._alertTreeChange(sHandle, flush=True)
sItem.setExpanded(isExpanded) if sItem is not None:
sItem.setExpanded(isExpanded)
return return
+27 -20
View File
@@ -55,6 +55,7 @@ from novelwriter.enum import (
nwDocMode, nwItemType, nwItemClass, nwAlert, nwWidget, nwState, nwView nwDocMode, nwItemType, nwItemClass, nwAlert, nwWidget, nwState, nwView
) )
from novelwriter.common import getGuiItem, hexToInt from novelwriter.common import getGuiItem, hexToInt
from novelwriter.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -104,7 +105,7 @@ class GuiMain(QMainWindow):
hWd = self.mainConf.pxInt(4) hWd = self.mainConf.pxInt(4)
# Main GUI Elements # Main GUI Elements
self.statusBar = GuiMainStatus(self) self.mainStatus = GuiMainStatus(self)
self.projView = GuiProjectView(self) self.projView = GuiProjectView(self)
self.novelView = GuiNovelView(self) self.novelView = GuiNovelView(self)
self.docEditor = GuiDocEditor(self) self.docEditor = GuiDocEditor(self)
@@ -189,7 +190,7 @@ class GuiMain(QMainWindow):
# Set Main Window Elements # Set Main Window Elements
self.setMenuBar(self.mainMenu) self.setMenuBar(self.mainMenu)
self.setCentralWidget(self.mainStack) self.setCentralWidget(self.mainStack)
self.setStatusBar(self.statusBar) self.setStatusBar(self.mainStatus)
self.addToolBar(Qt.LeftToolBarArea, self.viewsBar) self.addToolBar(Qt.LeftToolBarArea, self.viewsBar)
self.setContextMenuPolicy(Qt.NoContextMenu) # Issue #1147 self.setContextMenuPolicy(Qt.NoContextMenu) # Issue #1147
@@ -211,8 +212,8 @@ class GuiMain(QMainWindow):
self.novelView.selectedItemChanged.connect(self.itemDetails.updateViewBox) self.novelView.selectedItemChanged.connect(self.itemDetails.updateViewBox)
self.novelView.openDocumentRequest.connect(self._openDocument) self.novelView.openDocumentRequest.connect(self._openDocument)
self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage) self.docEditor.spellDictionaryChanged.connect(self.mainStatus.setLanguage)
self.docEditor.docEditedStatusChanged.connect(self.statusBar.doUpdateDocumentStatus) self.docEditor.docEditedStatusChanged.connect(self.mainStatus.doUpdateDocumentStatus)
self.docEditor.docCountsChanged.connect(self.itemDetails.updateCounts) self.docEditor.docCountsChanged.connect(self.itemDetails.updateCounts)
self.docEditor.docCountsChanged.connect(self.projView.updateCounts) self.docEditor.docCountsChanged.connect(self.projView.updateCounts)
self.docEditor.loadDocumentTagRequest.connect(self._followTag) self.docEditor.loadDocumentTagRequest.connect(self._followTag)
@@ -254,7 +255,7 @@ class GuiMain(QMainWindow):
keyEscape.activated.connect(self._keyPressEscape) keyEscape.activated.connect(self._keyPressEscape)
# Forward Functions # Forward Functions
self.setStatus = self.statusBar.setStatus self.setStatus = self.mainStatus.setStatus
# Force a show of the GUI # Force a show of the GUI
self.show() self.show()
@@ -266,7 +267,7 @@ class GuiMain(QMainWindow):
self.initMain() self.initMain()
self.asProjTimer.start() self.asProjTimer.start()
self.asDocTimer.start() self.asDocTimer.start()
self.statusBar.clearStatus() self.mainStatus.clearStatus()
# Handle Windows Mode # Handle Windows Mode
self.showNormal() self.showNormal()
@@ -307,7 +308,7 @@ class GuiMain(QMainWindow):
self.outlineView.clearProject() self.outlineView.clearProject()
# General # General
self.statusBar.clearStatus() self.mainStatus.clearStatus()
self._updateWindowTitle() self._updateWindowTitle()
return True return True
@@ -353,7 +354,7 @@ class GuiMain(QMainWindow):
logger.error("No projData or projPath set") logger.error("No projData or projPath set")
return False return False
if os.path.isfile(os.path.join(projPath, self.theProject.projFile)): if os.path.isfile(os.path.join(projPath, nwFiles.PROJ_FILE)):
self.makeAlert(self.tr( self.makeAlert(self.tr(
"A project already exists in that location. " "A project already exists in that location. "
"Please choose another folder." "Please choose another folder."
@@ -376,10 +377,10 @@ class GuiMain(QMainWindow):
self.outlineView.openProjectTasks() self.outlineView.openProjectTasks()
self.rebuildIndex(beQuiet=True) self.rebuildIndex(beQuiet=True)
self.statusBar.setRefTime(self.theProject.projOpened) self.mainStatus.setRefTime(self.theProject.projOpened)
self.statusBar.setProjectStatus(nwState.GOOD) self.mainStatus.setProjectStatus(nwState.GOOD)
self.statusBar.setDocumentStatus(nwState.NONE) self.mainStatus.setDocumentStatus(nwState.NONE)
self.statusBar.setStatus(self.tr("New project created ...")) self.mainStatus.setStatus(self.tr("New project created ..."))
self._updateWindowTitle(self.theProject.projName) self._updateWindowTitle(self.theProject.projName)
@@ -523,7 +524,7 @@ class GuiMain(QMainWindow):
self.rebuildTrees() self.rebuildTrees()
self.docEditor.setDictionaries() self.docEditor.setDictionaries()
self.docEditor.toggleSpellCheck(self.theProject.spellCheck) self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
self.statusBar.setRefTime(self.theProject.projOpened) self.mainStatus.setRefTime(self.theProject.projOpened)
self.projView.openProjectTasks() self.projView.openProjectTasks()
self.novelView.openProjectTasks() self.novelView.openProjectTasks()
self.outlineView.openProjectTasks() self.outlineView.openProjectTasks()
@@ -625,7 +626,7 @@ class GuiMain(QMainWindow):
fHandle = None # The first file handle we encounter fHandle = None # The first file handle we encounter
foundIt = False # We've found tHandle, pick the next we see foundIt = False # We've found tHandle, pick the next we see
for tItem in self.theProject.tree: for tItem in self.theProject.tree:
if not self.theProject.tree.checkType(tItem.itemHandle, nwItemType.FILE): if tItem is None or not tItem.isFileType():
continue continue
if fHandle is None: if fHandle is None:
fHandle = tItem.itemHandle fHandle = tItem.itemHandle
@@ -949,6 +950,7 @@ class GuiMain(QMainWindow):
dlgDetails = getGuiItem("GuiProjectDetails") dlgDetails = getGuiItem("GuiProjectDetails")
if dlgDetails is None: if dlgDetails is None:
dlgDetails = GuiProjectDetails(self) dlgDetails = GuiProjectDetails(self)
assert isinstance(dlgDetails, GuiProjectDetails)
dlgDetails.setModal(False) dlgDetails.setModal(False)
dlgDetails.show() dlgDetails.show()
@@ -967,6 +969,7 @@ class GuiMain(QMainWindow):
dlgBuild = getGuiItem("GuiBuildNovel") dlgBuild = getGuiItem("GuiBuildNovel")
if dlgBuild is None: if dlgBuild is None:
dlgBuild = GuiBuildNovel(self) dlgBuild = GuiBuildNovel(self)
assert isinstance(dlgBuild, GuiBuildNovel)
dlgBuild.setModal(False) dlgBuild.setModal(False)
dlgBuild.show() dlgBuild.show()
@@ -986,6 +989,7 @@ class GuiMain(QMainWindow):
dlgLipsum = getGuiItem("GuiLipsum") dlgLipsum = getGuiItem("GuiLipsum")
if dlgLipsum is None: if dlgLipsum is None:
dlgLipsum = GuiLipsum(self) dlgLipsum = GuiLipsum(self)
assert isinstance(dlgLipsum, GuiLipsum)
dlgLipsum.setModal(False) dlgLipsum.setModal(False)
dlgLipsum.show() dlgLipsum.show()
@@ -1020,6 +1024,7 @@ class GuiMain(QMainWindow):
dlgStats = getGuiItem("GuiWritingStats") dlgStats = getGuiItem("GuiWritingStats")
if dlgStats is None: if dlgStats is None:
dlgStats = GuiWritingStats(self) dlgStats = GuiWritingStats(self)
assert isinstance(dlgStats, GuiWritingStats)
dlgStats.setModal(False) dlgStats.setModal(False)
dlgStats.show() dlgStats.show()
@@ -1035,6 +1040,7 @@ class GuiMain(QMainWindow):
dlgAbout = getGuiItem("GuiAbout") dlgAbout = getGuiItem("GuiAbout")
if dlgAbout is None: if dlgAbout is None:
dlgAbout = GuiAbout(self) dlgAbout = GuiAbout(self)
assert isinstance(dlgAbout, GuiAbout)
dlgAbout.setModal(True) dlgAbout.setModal(True)
dlgAbout.show() dlgAbout.show()
@@ -1060,6 +1066,7 @@ class GuiMain(QMainWindow):
dlgUpdate = getGuiItem("GuiUpdates") dlgUpdate = getGuiItem("GuiUpdates")
if dlgUpdate is None: if dlgUpdate is None:
dlgUpdate = GuiUpdates(self) dlgUpdate = GuiUpdates(self)
assert isinstance(dlgUpdate, GuiUpdates)
dlgUpdate.setModal(True) dlgUpdate.setModal(True)
dlgUpdate.show() dlgUpdate.show()
@@ -1221,7 +1228,7 @@ class GuiMain(QMainWindow):
isVisible = not self.isFocusMode isVisible = not self.isFocusMode
self.treePane.setVisible(isVisible) self.treePane.setVisible(isVisible)
self.statusBar.setVisible(isVisible) self.mainStatus.setVisible(isVisible)
self.mainMenu.setVisible(isVisible) self.mainMenu.setVisible(isVisible)
self.viewsBar.setVisible(isVisible) self.viewsBar.setVisible(isVisible)
@@ -1505,12 +1512,12 @@ class GuiMain(QMainWindow):
if editIdle or userIdle: if editIdle or userIdle:
self.idleTime += currTime - self.idleRefTime self.idleTime += currTime - self.idleRefTime
self.statusBar.setUserIdle(True) self.mainStatus.setUserIdle(True)
else: else:
self.statusBar.setUserIdle(False) self.mainStatus.setUserIdle(False)
self.idleRefTime = currTime self.idleRefTime = currTime
self.statusBar.updateTime(idleTime=self.idleTime) self.mainStatus.updateTime(idleTime=self.idleTime)
return return
@@ -1519,7 +1526,7 @@ class GuiMain(QMainWindow):
"""Update the word count on the status bar. """Update the word count on the status bar.
""" """
if not self.hasProject: if not self.hasProject:
self.statusBar.setProjectStats(0, 0) self.mainStatus.setProjectStats(0, 0)
self.theProject.updateWordCounts() self.theProject.updateWordCounts()
if self.mainConf.incNotesWCount: if self.mainConf.incNotesWCount:
@@ -1529,7 +1536,7 @@ class GuiMain(QMainWindow):
currWords = self.theProject.currNovelWC currWords = self.theProject.currNovelWC
diffWords = currWords - self.theProject.lastNovelWC diffWords = currWords - self.theProject.lastNovelWC
self.statusBar.setProjectStats(currWords, diffWords) self.mainStatus.setProjectStats(currWords, diffWords)
return return
+4 -3
View File
@@ -112,9 +112,10 @@ class GuiWritingStats(QDialog):
self.listBox.setColumnWidth(self.C_COUNT, wCol3) self.listBox.setColumnWidth(self.C_COUNT, wCol3)
hHeader = self.listBox.headerItem() hHeader = self.listBox.headerItem()
hHeader.setTextAlignment(self.C_LENGTH, Qt.AlignRight) if hHeader is not None:
hHeader.setTextAlignment(self.C_IDLE, Qt.AlignRight) hHeader.setTextAlignment(self.C_LENGTH, Qt.AlignRight)
hHeader.setTextAlignment(self.C_COUNT, Qt.AlignRight) hHeader.setTextAlignment(self.C_IDLE, Qt.AlignRight)
hHeader.setTextAlignment(self.C_COUNT, Qt.AlignRight)
sortCol = minmax(pOptions.getInt("GuiWritingStats", "sortCol", 0), 0, 2) sortCol = minmax(pOptions.getInt("GuiWritingStats", "sortCol", 0), 0, 2)
sortOrder = checkIntTuple( sortOrder = checkIntTuple(
+1 -1
View File
@@ -30,7 +30,7 @@ class MockGuiMain:
self.mainConf = None self.mainConf = None
self.hasProject = True self.hasProject = True
self.theProject = None self.theProject = None
self.statusBar = MockStatusBar() self.mainStatus = MockStatusBar()
# Test Variables # Test Variables
self.askResponse = True self.askResponse = True
+5 -10
View File
@@ -556,13 +556,13 @@ def testBaseCommon_EnsureFolder(monkeypatch, fncDir):
assert ensureFolder(newDir1) is True assert ensureFolder(newDir1) is True
assert os.path.isdir(newDir1) assert os.path.isdir(newDir1)
assert ensureFolder("newDir2", parentPath=fncDir) is True assert ensureFolder("newDir2", parent=fncDir) is True
assert os.path.isdir(newDir2) assert os.path.isdir(newDir2)
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("os.mkdir", causeOSError) mp.setattr("os.mkdir", causeOSError)
errLog = [] errLog = []
assert ensureFolder("newDir3", parentPath=fncDir, errLog=errLog) is False assert ensureFolder("newDir3", parent=fncDir, errLog=errLog) is False
assert errLog[0] == f"Could not create folder: {newDir3}" assert errLog[0] == f"Could not create folder: {newDir3}"
assert not os.path.isdir(newDir3) assert not os.path.isdir(newDir3)
@@ -673,10 +673,10 @@ def testBaseCommon_NWConfigParser(fncDir):
# Read Float # Read Float
assert cfgParser.rdFlt("main", "intopt1", 13.0) == 42.0 assert cfgParser.rdFlt("main", "intopt1", 13.0) == 42.0
assert cfgParser.rdFlt("main", "float1", 13.0) == 4.2 assert cfgParser.rdFlt("main", "float1", 13.0) == 4.2
assert cfgParser.rdInt("main", "stropt", 13.0) == 13.0 assert cfgParser.rdFlt("main", "stropt", 13.0) == 13.0
assert cfgParser.rdInt("nope", "intopt1", 13.0) == 13.0 assert cfgParser.rdFlt("nope", "intopt1", 13.0) == 13.0
assert cfgParser.rdInt("main", "blabla", 13.0) == 13.0 assert cfgParser.rdFlt("main", "blabla", 13.0) == 13.0
# Read String List # Read String List
assert cfgParser.rdStrList("main", "list1", []) == [] assert cfgParser.rdStrList("main", "list1", []) == []
@@ -704,9 +704,4 @@ def testBaseCommon_NWConfigParser(fncDir):
assert cfgParser.rdIntList("nope", "list2", [1]) == [1] assert cfgParser.rdIntList("nope", "list2", [1]) == [1]
assert cfgParser.rdIntList("main", "blabla", [1]) == [1] assert cfgParser.rdIntList("main", "blabla", [1]) == [1]
# Internal
# ========
assert cfgParser._parseLine("main", "stropt", None, 999) is None
# END Test testBaseCommon_NWConfigParser # END Test testBaseCommon_NWConfigParser
+5 -6
View File
@@ -31,6 +31,7 @@ from PyQt5.QtWidgets import QMessageBox, QInputDialog
from novelwriter.enum import nwItemType, nwView, nwWidget from novelwriter.enum import nwItemType, nwView, nwWidget
from novelwriter.tools import GuiProjectWizard from novelwriter.tools import GuiProjectWizard
from novelwriter.dialogs import GuiEditLabel from novelwriter.dialogs import GuiEditLabel
from novelwriter.constants import nwFiles
from novelwriter.gui.outline import GuiOutlineView from novelwriter.gui.outline import GuiOutlineView
from novelwriter.gui.projtree import GuiProjectTree from novelwriter.gui.projtree import GuiProjectTree
from novelwriter.gui.doceditor import GuiDocEditor from novelwriter.gui.doceditor import GuiDocEditor
@@ -91,7 +92,7 @@ def testGuiMain_NewProject(monkeypatch, nwGUI, fncProj):
assert nwGUI.newProject(projData={}) is False assert nwGUI.newProject(projData={}) is False
# Project file already exists # Project file already exists
projFile = os.path.join(fncProj, nwGUI.theProject.projFile) projFile = os.path.join(fncProj, nwFiles.PROJ_FILE)
writeFile(projFile, "Stuff") writeFile(projFile, "Stuff")
assert nwGUI.newProject(projData={"projPath": fncProj}) is False assert nwGUI.newProject(projData={"projPath": fncProj}) is False
os.unlink(projFile) os.unlink(projFile)
@@ -102,7 +103,7 @@ def testGuiMain_NewProject(monkeypatch, nwGUI, fncProj):
# This one should work just fine # This one should work just fine
assert nwGUI.newProject(projData={"projPath": fncProj}) is True assert nwGUI.newProject(projData={"projPath": fncProj}) is True
assert os.path.isfile(os.path.join(fncProj, nwGUI.theProject.projFile)) assert os.path.isfile(os.path.join(fncProj, nwFiles.PROJ_FILE))
assert os.path.isdir(os.path.join(fncProj, "content")) assert os.path.isdir(os.path.join(fncProj, "content"))
# END Test testGuiMain_NewProject # END Test testGuiMain_NewProject
@@ -183,7 +184,6 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
assert nwGUI.theProject.tree.trashRoot() is None assert nwGUI.theProject.tree.trashRoot() is None
assert nwGUI.theProject.projPath is None assert nwGUI.theProject.projPath is None
assert nwGUI.theProject.projMeta is None assert nwGUI.theProject.projMeta is None
assert nwGUI.theProject.projFile == "nwProject.nwx"
assert nwGUI.theProject.projName == "" assert nwGUI.theProject.projName == ""
assert nwGUI.theProject.bookTitle == "" assert nwGUI.theProject.bookTitle == ""
assert len(nwGUI.theProject.bookAuthors) == 0 assert len(nwGUI.theProject.bookAuthors) == 0
@@ -208,7 +208,6 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
assert nwGUI.theProject.tree.trashRoot() is None assert nwGUI.theProject.tree.trashRoot() is None
assert nwGUI.theProject.projPath == fncProj assert nwGUI.theProject.projPath == fncProj
assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta") assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta")
assert nwGUI.theProject.projFile == "nwProject.nwx"
assert nwGUI.theProject.projName == "New Project" assert nwGUI.theProject.projName == "New Project"
assert nwGUI.theProject.bookTitle == "New Novel" assert nwGUI.theProject.bookTitle == "New Novel"
assert len(nwGUI.theProject.bookAuthors) == 1 assert len(nwGUI.theProject.bookAuthors) == 1
@@ -575,7 +574,7 @@ def testGuiMain_FocusFullMode(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
# Enable focus mode # Enable focus mode
assert nwGUI.toggleFocusMode() is True assert nwGUI.toggleFocusMode() is True
assert nwGUI.treePane.isVisible() is False assert nwGUI.treePane.isVisible() is False
assert nwGUI.statusBar.isVisible() is False assert nwGUI.mainStatus.isVisible() is False
assert nwGUI.mainMenu.isVisible() is False assert nwGUI.mainMenu.isVisible() is False
assert nwGUI.viewsBar.isVisible() is False assert nwGUI.viewsBar.isVisible() is False
assert nwGUI.splitView.isVisible() is False assert nwGUI.splitView.isVisible() is False
@@ -583,7 +582,7 @@ def testGuiMain_FocusFullMode(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
# Disable focus mode # Disable focus mode
assert nwGUI.toggleFocusMode() is True assert nwGUI.toggleFocusMode() is True
assert nwGUI.treePane.isVisible() is True assert nwGUI.treePane.isVisible() is True
assert nwGUI.statusBar.isVisible() is True assert nwGUI.mainStatus.isVisible() is True
assert nwGUI.mainMenu.isVisible() is True assert nwGUI.mainMenu.isVisible() is True
assert nwGUI.viewsBar.isVisible() is True assert nwGUI.viewsBar.isVisible() is True
assert nwGUI.splitView.isVisible() is True assert nwGUI.splitView.isVisible() is True
+37 -37
View File
@@ -45,57 +45,57 @@ def testGuiStatusBar_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
# Reference Time # Reference Time
refTime = time.time() refTime = time.time()
nwGUI.statusBar.setRefTime(refTime) nwGUI.mainStatus.setRefTime(refTime)
assert nwGUI.statusBar.refTime == refTime assert nwGUI.mainStatus.refTime == refTime
# Project Status # Project Status
nwGUI.statusBar.setProjectStatus(nwState.NONE) nwGUI.mainStatus.setProjectStatus(nwState.NONE)
assert nwGUI.statusBar.projIcon._theCol == nwGUI.statusBar.projIcon._colNone assert nwGUI.mainStatus.projIcon._theCol == nwGUI.mainStatus.projIcon._colNone
nwGUI.statusBar.setProjectStatus(nwState.BAD) nwGUI.mainStatus.setProjectStatus(nwState.BAD)
assert nwGUI.statusBar.projIcon._theCol == nwGUI.statusBar.projIcon._colBad assert nwGUI.mainStatus.projIcon._theCol == nwGUI.mainStatus.projIcon._colBad
nwGUI.statusBar.setProjectStatus(nwState.GOOD) nwGUI.mainStatus.setProjectStatus(nwState.GOOD)
assert nwGUI.statusBar.projIcon._theCol == nwGUI.statusBar.projIcon._colGood assert nwGUI.mainStatus.projIcon._theCol == nwGUI.mainStatus.projIcon._colGood
# Document Status # Document Status
nwGUI.statusBar.setDocumentStatus(nwState.NONE) nwGUI.mainStatus.setDocumentStatus(nwState.NONE)
assert nwGUI.statusBar.docIcon._theCol == nwGUI.statusBar.docIcon._colNone assert nwGUI.mainStatus.docIcon._theCol == nwGUI.mainStatus.docIcon._colNone
nwGUI.statusBar.setDocumentStatus(nwState.BAD) nwGUI.mainStatus.setDocumentStatus(nwState.BAD)
assert nwGUI.statusBar.docIcon._theCol == nwGUI.statusBar.docIcon._colBad assert nwGUI.mainStatus.docIcon._theCol == nwGUI.mainStatus.docIcon._colBad
nwGUI.statusBar.setDocumentStatus(nwState.GOOD) nwGUI.mainStatus.setDocumentStatus(nwState.GOOD)
assert nwGUI.statusBar.docIcon._theCol == nwGUI.statusBar.docIcon._colGood assert nwGUI.mainStatus.docIcon._theCol == nwGUI.mainStatus.docIcon._colGood
# Idle Status # Idle Status
nwGUI.statusBar.mainConf.stopWhenIdle = False nwGUI.mainStatus.mainConf.stopWhenIdle = False
nwGUI.statusBar.setUserIdle(True) nwGUI.mainStatus.setUserIdle(True)
nwGUI.statusBar.updateTime() nwGUI.mainStatus.updateTime()
assert nwGUI.statusBar.userIdle is False assert nwGUI.mainStatus.userIdle is False
assert nwGUI.statusBar.timeText.text() == "00:00:00" assert nwGUI.mainStatus.timeText.text() == "00:00:00"
nwGUI.statusBar.mainConf.stopWhenIdle = True nwGUI.mainStatus.mainConf.stopWhenIdle = True
nwGUI.statusBar.setUserIdle(True) nwGUI.mainStatus.setUserIdle(True)
nwGUI.statusBar.updateTime(5) nwGUI.mainStatus.updateTime(5)
assert nwGUI.statusBar.userIdle is True assert nwGUI.mainStatus.userIdle is True
assert nwGUI.statusBar.timeText.text() != "00:00:00" assert nwGUI.mainStatus.timeText.text() != "00:00:00"
nwGUI.statusBar.setUserIdle(False) nwGUI.mainStatus.setUserIdle(False)
nwGUI.statusBar.updateTime(5) nwGUI.mainStatus.updateTime(5)
assert nwGUI.statusBar.userIdle is False assert nwGUI.mainStatus.userIdle is False
assert nwGUI.statusBar.timeText.text() != "00:00:00" assert nwGUI.mainStatus.timeText.text() != "00:00:00"
# Language # Language
nwGUI.statusBar.setLanguage("None", "None") nwGUI.mainStatus.setLanguage("None", "None")
assert nwGUI.statusBar.langText.text() == "None" assert nwGUI.mainStatus.langText.text() == "None"
nwGUI.statusBar.setLanguage("en", "None") nwGUI.mainStatus.setLanguage("en", "None")
assert nwGUI.statusBar.langText.text() == "American English" assert nwGUI.mainStatus.langText.text() == "American English"
# Project Stats # Project Stats
nwGUI.statusBar.mainConf.incNotesWCount = False nwGUI.mainStatus.mainConf.incNotesWCount = False
nwGUI._updateStatusWordCount() nwGUI._updateStatusWordCount()
assert nwGUI.statusBar.statsText.text() == "Words: 9 (+9)" assert nwGUI.mainStatus.statsText.text() == "Words: 9 (+9)"
nwGUI.statusBar.mainConf.incNotesWCount = True nwGUI.mainStatus.mainConf.incNotesWCount = True
nwGUI._updateStatusWordCount() nwGUI._updateStatusWordCount()
assert nwGUI.statusBar.statsText.text() == "Words: 11 (+11)" assert nwGUI.mainStatus.statsText.text() == "Words: 11 (+11)"
# qtbot.stopForInteraction() # qtbot.stop()
# END Test testGuiStatusBar_Init # END Test testGuiStatusBar_Init