Fix various issues in the code (#1197)
This commit is contained in:
+99
-127
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user