Project tree status and total word count changes (#882)
* Fix some inconsistencies in source file docstrings * Remove the option to show status text in project tree * Change how total word counts are calculated and propagated * Fix tests and improve coverage * Add setting in preferences * Add missing word count timer to config file
This commit is contained in:
committed by
GitHub
parent
b9311e84ce
commit
3c8cb34b0a
+12
-4
@@ -4,7 +4,7 @@ novelWriter – Common Functions
|
|||||||
Various common functions
|
Various common functions
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-05-12 [0.1.0]
|
Created: 2019-05-12 [0.1]
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2021, Veronica Berglyd Olsen
|
Copyright 2018–2021, Veronica Berglyd Olsen
|
||||||
@@ -441,9 +441,10 @@ class NWConfigParser(ConfigParser):
|
|||||||
|
|
||||||
CNF_STR = 0
|
CNF_STR = 0
|
||||||
CNF_INT = 1
|
CNF_INT = 1
|
||||||
CNF_BOOL = 2
|
CNF_FLOAT = 2
|
||||||
CNF_S_LST = 3
|
CNF_BOOL = 3
|
||||||
CNF_I_LST = 4
|
CNF_S_LST = 4
|
||||||
|
CNF_I_LST = 5
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -458,6 +459,11 @@ class NWConfigParser(ConfigParser):
|
|||||||
"""
|
"""
|
||||||
return self._parseLine(section, option, default, self.CNF_INT)
|
return self._parseLine(section, option, default, self.CNF_INT)
|
||||||
|
|
||||||
|
def rdFlt(self, section, option, default):
|
||||||
|
"""Read float value.
|
||||||
|
"""
|
||||||
|
return self._parseLine(section, option, default, self.CNF_FLOAT)
|
||||||
|
|
||||||
def rdBool(self, section, option, default):
|
def rdBool(self, section, option, default):
|
||||||
"""Read boolean value.
|
"""Read boolean value.
|
||||||
"""
|
"""
|
||||||
@@ -503,6 +509,8 @@ class NWConfigParser(ConfigParser):
|
|||||||
return self.get(section, option)
|
return self.get(section, option)
|
||||||
elif type == self.CNF_INT:
|
elif type == self.CNF_INT:
|
||||||
return self.getint(section, option)
|
return self.getint(section, option)
|
||||||
|
elif type == self.CNF_FLOAT:
|
||||||
|
return self.getfloat(section, option)
|
||||||
elif type == self.CNF_BOOL:
|
elif type == self.CNF_BOOL:
|
||||||
return self.getboolean(section, option)
|
return self.getboolean(section, option)
|
||||||
elif type in (self.CNF_I_LST, self.CNF_S_LST):
|
elif type in (self.CNF_I_LST, self.CNF_S_LST):
|
||||||
|
|||||||
+13
-11
@@ -108,7 +108,6 @@ class Config:
|
|||||||
# Features
|
# Features
|
||||||
self.hideVScroll = False # Hide vertical scroll bars on main widgets
|
self.hideVScroll = False # Hide vertical scroll bars on main widgets
|
||||||
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
|
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
|
||||||
self.fullStatus = True # Show the full status text in the project tree
|
|
||||||
self.emphLabels = True # Add emphasis to H1 and H2 item labels
|
self.emphLabels = True # Add emphasis to H1 and H2 item labels
|
||||||
|
|
||||||
# Project
|
# Project
|
||||||
@@ -145,6 +144,7 @@ class Config:
|
|||||||
|
|
||||||
self.wordCountTimer = 5.0 # Interval for word count update in seconds
|
self.wordCountTimer = 5.0 # Interval for word count update in seconds
|
||||||
self.bigDocLimit = 800 # Size threshold for heavy editor features in kilobytes
|
self.bigDocLimit = 800 # Size threshold for heavy editor features in kilobytes
|
||||||
|
self.incNotesWCount = True # The status bar word count includes notes
|
||||||
|
|
||||||
self.highlightQuotes = True # Highlight text in quotes
|
self.highlightQuotes = True # Highlight text in quotes
|
||||||
self.allowOpenSQuote = False # Allow open-ended single quotes
|
self.allowOpenSQuote = False # Allow open-ended single quotes
|
||||||
@@ -179,9 +179,9 @@ class Config:
|
|||||||
self.askBeforeBackup = True
|
self.askBeforeBackup = True
|
||||||
|
|
||||||
# State
|
# State
|
||||||
self.showRefPanel = True
|
self.showRefPanel = True # The reference panel for the viewer is visible
|
||||||
self.viewComments = True
|
self.viewComments = True # Comments are shown in the viewer
|
||||||
self.viewSynopsis = True
|
self.viewSynopsis = True # Synopsis is shown in the viewer
|
||||||
|
|
||||||
# Check Qt5 Versions
|
# Check Qt5 Versions
|
||||||
verQt = splitVersionNumber(QT_VERSION_STR)
|
verQt = splitVersionNumber(QT_VERSION_STR)
|
||||||
@@ -466,7 +466,6 @@ class Config:
|
|||||||
cnfSec = "Project"
|
cnfSec = "Project"
|
||||||
self.autoSaveProj = theConf.rdInt(cnfSec, "autosaveproject", self.autoSaveProj)
|
self.autoSaveProj = theConf.rdInt(cnfSec, "autosaveproject", self.autoSaveProj)
|
||||||
self.autoSaveDoc = theConf.rdInt(cnfSec, "autosavedoc", self.autoSaveDoc)
|
self.autoSaveDoc = theConf.rdInt(cnfSec, "autosavedoc", self.autoSaveDoc)
|
||||||
self.fullStatus = theConf.rdBool(cnfSec, "fullstatus", self.fullStatus)
|
|
||||||
self.emphLabels = theConf.rdBool(cnfSec, "emphlabels", self.emphLabels)
|
self.emphLabels = theConf.rdBool(cnfSec, "emphlabels", self.emphLabels)
|
||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
@@ -498,7 +497,9 @@ class Config:
|
|||||||
self.showTabsNSpaces = theConf.rdBool(cnfSec, "showtabsnspaces", self.showTabsNSpaces)
|
self.showTabsNSpaces = theConf.rdBool(cnfSec, "showtabsnspaces", self.showTabsNSpaces)
|
||||||
self.showLineEndings = theConf.rdBool(cnfSec, "showlineendings", self.showLineEndings)
|
self.showLineEndings = theConf.rdBool(cnfSec, "showlineendings", self.showLineEndings)
|
||||||
self.showMultiSpaces = theConf.rdBool(cnfSec, "showmultispaces", self.showMultiSpaces)
|
self.showMultiSpaces = theConf.rdBool(cnfSec, "showmultispaces", self.showMultiSpaces)
|
||||||
|
self.wordCountTimer = theConf.rdFlt(cnfSec, "wordcounttimer", self.wordCountTimer)
|
||||||
self.bigDocLimit = theConf.rdInt(cnfSec, "bigdoclimit", self.bigDocLimit)
|
self.bigDocLimit = theConf.rdInt(cnfSec, "bigdoclimit", self.bigDocLimit)
|
||||||
|
self.incNotesWCount = theConf.rdBool(cnfSec, "incnoteswcount", self.incNotesWCount)
|
||||||
self.showFullPath = theConf.rdBool(cnfSec, "showfullpath", self.showFullPath)
|
self.showFullPath = theConf.rdBool(cnfSec, "showfullpath", self.showFullPath)
|
||||||
self.highlightQuotes = theConf.rdBool(cnfSec, "highlightquotes", self.highlightQuotes)
|
self.highlightQuotes = theConf.rdBool(cnfSec, "highlightquotes", self.highlightQuotes)
|
||||||
self.allowOpenSQuote = theConf.rdBool(cnfSec, "allowopensquote", self.allowOpenSQuote)
|
self.allowOpenSQuote = theConf.rdBool(cnfSec, "allowopensquote", self.allowOpenSQuote)
|
||||||
@@ -588,7 +589,6 @@ class Config:
|
|||||||
theConf["Project"] = {
|
theConf["Project"] = {
|
||||||
"autosaveproject": str(self.autoSaveProj),
|
"autosaveproject": str(self.autoSaveProj),
|
||||||
"autosavedoc": str(self.autoSaveDoc),
|
"autosavedoc": str(self.autoSaveDoc),
|
||||||
"fullstatus": str(self.fullStatus),
|
|
||||||
"emphlabels": str(self.emphLabels),
|
"emphlabels": str(self.emphLabels),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,7 +620,9 @@ class Config:
|
|||||||
"showtabsnspaces": str(self.showTabsNSpaces),
|
"showtabsnspaces": str(self.showTabsNSpaces),
|
||||||
"showlineendings": str(self.showLineEndings),
|
"showlineendings": str(self.showLineEndings),
|
||||||
"showmultispaces": str(self.showMultiSpaces),
|
"showmultispaces": str(self.showMultiSpaces),
|
||||||
|
"wordcounttimer": str(self.wordCountTimer),
|
||||||
"bigdoclimit": str(self.bigDocLimit),
|
"bigdoclimit": str(self.bigDocLimit),
|
||||||
|
"incnoteswcount": str(self.incNotesWCount),
|
||||||
"showfullpath": str(self.showFullPath),
|
"showfullpath": str(self.showFullPath),
|
||||||
"highlightquotes": str(self.highlightQuotes),
|
"highlightquotes": str(self.highlightQuotes),
|
||||||
"allowopensquote": str(self.allowOpenSQuote),
|
"allowopensquote": str(self.allowOpenSQuote),
|
||||||
@@ -821,7 +823,7 @@ class Config:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def setDocPanePos(self, panePos):
|
def setDocPanePos(self, panePos):
|
||||||
self.docPanePos = [int(x/self.guiScale) for x in panePos]
|
self.docPanePos = [int(x/self.guiScale) for x in panePos]
|
||||||
self.confChanged = True
|
self.confChanged = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -832,22 +834,22 @@ class Config:
|
|||||||
|
|
||||||
def setOutlinePanePos(self, panePos):
|
def setOutlinePanePos(self, panePos):
|
||||||
self.outlnPanePos = [int(x/self.guiScale) for x in panePos]
|
self.outlnPanePos = [int(x/self.guiScale) for x in panePos]
|
||||||
self.confChanged = True
|
self.confChanged = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setShowRefPanel(self, checkState):
|
def setShowRefPanel(self, checkState):
|
||||||
self.showRefPanel = checkState
|
self.showRefPanel = checkState
|
||||||
self.confChanged = True
|
self.confChanged = True
|
||||||
return self.showRefPanel
|
return self.showRefPanel
|
||||||
|
|
||||||
def setViewComments(self, viewState):
|
def setViewComments(self, viewState):
|
||||||
self.viewComments = viewState
|
self.viewComments = viewState
|
||||||
self.confChanged = True
|
self.confChanged = True
|
||||||
return self.viewComments
|
return self.viewComments
|
||||||
|
|
||||||
def setViewSynopsis(self, viewState):
|
def setViewSynopsis(self, viewState):
|
||||||
self.viewSynopsis = viewState
|
self.viewSynopsis = viewState
|
||||||
self.confChanged = True
|
self.confChanged = True
|
||||||
return self.viewSynopsis
|
return self.viewSynopsis
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
+29
-29
@@ -99,9 +99,11 @@ class NWProject():
|
|||||||
self.lastEdited = None # The handle of the last file to be edited
|
self.lastEdited = None # The handle of the last file to be edited
|
||||||
self.lastViewed = None # The handle of the last file to be viewed
|
self.lastViewed = None # The handle of the last file to be viewed
|
||||||
self.lastWCount = 0 # The project word count from last session
|
self.lastWCount = 0 # The project word count from last session
|
||||||
|
self.lastNovelWC = 0 # The novel files word count from last session
|
||||||
|
self.lastNotesWC = 0 # The note files word count from last session
|
||||||
self.currWCount = 0 # The project word count in current session
|
self.currWCount = 0 # The project word count in current session
|
||||||
self.novelWCount = 0 # Total number of words in novel files
|
self.currNovelWC = 0 # The novel files word count in cutrent session
|
||||||
self.notesWCount = 0 # Total number of words in note files
|
self.currNotesWC = 0 # The note files word count in cutrent session
|
||||||
self.doBackup = True # Run project backup on exit
|
self.doBackup = True # Run project backup on exit
|
||||||
|
|
||||||
# Internal Mapping
|
# Internal Mapping
|
||||||
@@ -226,9 +228,11 @@ class NWProject():
|
|||||||
self.lastEdited = None
|
self.lastEdited = None
|
||||||
self.lastViewed = None
|
self.lastViewed = None
|
||||||
self.lastWCount = 0
|
self.lastWCount = 0
|
||||||
|
self.lastNovelWC = 0
|
||||||
|
self.lastNotesWC = 0
|
||||||
self.currWCount = 0
|
self.currWCount = 0
|
||||||
self.novelWCount = 0
|
self.currNovelWC = 0
|
||||||
self.notesWCount = 0
|
self.currNotesWC = 0
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -566,9 +570,9 @@ class NWProject():
|
|||||||
elif xItem.tag == "lastWordCount":
|
elif xItem.tag == "lastWordCount":
|
||||||
self.lastWCount = checkInt(xItem.text, 0, False)
|
self.lastWCount = checkInt(xItem.text, 0, False)
|
||||||
elif xItem.tag == "novelWordCount":
|
elif xItem.tag == "novelWordCount":
|
||||||
self.novelWCount = checkInt(xItem.text, 0, False)
|
self.lastNovelWC = checkInt(xItem.text, 0, False)
|
||||||
elif xItem.tag == "notesWordCount":
|
elif xItem.tag == "notesWordCount":
|
||||||
self.notesWCount = checkInt(xItem.text, 0, False)
|
self.lastNotesWC = checkInt(xItem.text, 0, False)
|
||||||
elif xItem.tag == "status":
|
elif xItem.tag == "status":
|
||||||
self.statusItems.unpackXML(xItem)
|
self.statusItems.unpackXML(xItem)
|
||||||
elif xItem.tag == "importance":
|
elif xItem.tag == "importance":
|
||||||
@@ -610,8 +614,8 @@ class NWProject():
|
|||||||
|
|
||||||
self._scanProjectFolder()
|
self._scanProjectFolder()
|
||||||
self._loadProjectLocalisation()
|
self._loadProjectLocalisation()
|
||||||
|
self.updateWordCounts()
|
||||||
|
|
||||||
self.currWCount = self.lastWCount
|
|
||||||
self.projOpened = time()
|
self.projOpened = time()
|
||||||
self.projAltered = False
|
self.projAltered = False
|
||||||
|
|
||||||
@@ -652,11 +656,8 @@ class NWProject():
|
|||||||
"timeStamp": formatTimeStamp(saveTime),
|
"timeStamp": formatTimeStamp(saveTime),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.updateWordCounts()
|
||||||
editTime = int(self.editTime + saveTime - self.projOpened)
|
editTime = int(self.editTime + saveTime - self.projOpened)
|
||||||
wcNovel, wcNotes = self.projTree.sumWords()
|
|
||||||
self.novelWCount = wcNovel
|
|
||||||
self.notesWCount = wcNotes
|
|
||||||
self.setProjectWordCount(wcNovel + wcNotes)
|
|
||||||
|
|
||||||
# Save Project Meta
|
# Save Project Meta
|
||||||
xProject = etree.SubElement(nwXML, "project")
|
xProject = etree.SubElement(nwXML, "project")
|
||||||
@@ -677,8 +678,8 @@ class NWProject():
|
|||||||
self._packProjectValue(xSettings, "lastEdited", self.lastEdited)
|
self._packProjectValue(xSettings, "lastEdited", self.lastEdited)
|
||||||
self._packProjectValue(xSettings, "lastViewed", self.lastViewed)
|
self._packProjectValue(xSettings, "lastViewed", self.lastViewed)
|
||||||
self._packProjectValue(xSettings, "lastWordCount", self.currWCount)
|
self._packProjectValue(xSettings, "lastWordCount", self.currWCount)
|
||||||
self._packProjectValue(xSettings, "novelWordCount", wcNovel)
|
self._packProjectValue(xSettings, "novelWordCount", self.currNovelWC)
|
||||||
self._packProjectValue(xSettings, "notesWordCount", wcNotes)
|
self._packProjectValue(xSettings, "notesWordCount", self.currNotesWC)
|
||||||
self._packProjectKeyValue(xSettings, "autoReplace", self.autoReplace)
|
self._packProjectKeyValue(xSettings, "autoReplace", self.autoReplace)
|
||||||
|
|
||||||
xTitleFmt = etree.SubElement(xSettings, "titleFormat")
|
xTitleFmt = etree.SubElement(xSettings, "titleFormat")
|
||||||
@@ -1067,14 +1068,6 @@ class NWProject():
|
|||||||
self.setProjectChanged(True)
|
self.setProjectChanged(True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setProjectWordCount(self, theCount):
|
|
||||||
"""Set the current project word count.
|
|
||||||
"""
|
|
||||||
if self.currWCount != theCount:
|
|
||||||
self.currWCount = theCount
|
|
||||||
self.setProjectChanged(True)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def setStatusColours(self, newCols):
|
def setStatusColours(self, newCols):
|
||||||
"""Update the list of novel file status flags. Also iterate
|
"""Update the list of novel file status flags. Also iterate
|
||||||
through the project and replace keys that have been renamed.
|
through the project and replace keys that have been renamed.
|
||||||
@@ -1145,11 +1138,6 @@ class NWProject():
|
|||||||
|
|
||||||
return authString
|
return authString
|
||||||
|
|
||||||
def getSessionWordCount(self):
|
|
||||||
"""Returns the number of words added or removed this session.
|
|
||||||
"""
|
|
||||||
return self.currWCount - self.lastWCount
|
|
||||||
|
|
||||||
def getCurrentEditTime(self):
|
def getCurrentEditTime(self):
|
||||||
"""Get the total project edit time, including the time spent in
|
"""Get the total project edit time, including the time spent in
|
||||||
the current session.
|
the current session.
|
||||||
@@ -1202,6 +1190,18 @@ class NWProject():
|
|||||||
# Class Methods
|
# Class Methods
|
||||||
##
|
##
|
||||||
|
|
||||||
|
def updateWordCounts(self):
|
||||||
|
"""Update the total word count values.
|
||||||
|
"""
|
||||||
|
wcNovel, wcNotes = self.projTree.sumWords()
|
||||||
|
wcTotal = wcNovel + wcNotes
|
||||||
|
if wcTotal != self.currWCount:
|
||||||
|
self.currNovelWC = wcNovel
|
||||||
|
self.currNotesWC = wcNotes
|
||||||
|
self.currWCount = wcTotal
|
||||||
|
self.setProjectChanged(True)
|
||||||
|
return
|
||||||
|
|
||||||
def countStatus(self):
|
def countStatus(self):
|
||||||
"""Count how many times the various status flags are used in the
|
"""Count how many times the various status flags are used in the
|
||||||
project tree. The counts themselves are kept in the NWStatus
|
project tree. The counts themselves are kept in the NWStatus
|
||||||
@@ -1460,7 +1460,7 @@ class NWProject():
|
|||||||
isFile = os.path.isfile(sessionFile)
|
isFile = os.path.isfile(sessionFile)
|
||||||
|
|
||||||
nowTime = time()
|
nowTime = time()
|
||||||
sessDiff = self.getSessionWordCount()
|
sessDiff = self.currWCount - self.lastWCount
|
||||||
sessTime = nowTime - self.projOpened
|
sessTime = nowTime - self.projOpened
|
||||||
|
|
||||||
logger.info("The session lasted %d sec and added %d words", int(sessTime), sessDiff)
|
logger.info("The session lasted %d sec and added %d words", int(sessTime), sessDiff)
|
||||||
@@ -1481,8 +1481,8 @@ class NWProject():
|
|||||||
outFile.write("%-19s %-19s %8d %8d %8d\n" % (
|
outFile.write("%-19s %-19s %8d %8d %8d\n" % (
|
||||||
formatTimeStamp(self.projOpened),
|
formatTimeStamp(self.projOpened),
|
||||||
formatTimeStamp(nowTime),
|
formatTimeStamp(nowTime),
|
||||||
self.novelWCount,
|
self.currNovelWC,
|
||||||
self.notesWCount,
|
self.currNotesWC,
|
||||||
int(idleTime),
|
int(idleTime),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ class NWTree():
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def sumWords(self):
|
def sumWords(self):
|
||||||
"""Loops over all entries and adds up the word counts.
|
"""Loop over all entries and add up the word counts.
|
||||||
"""
|
"""
|
||||||
noteWords = 0
|
noteWords = 0
|
||||||
novelWords = 0
|
novelWords = 0
|
||||||
|
|||||||
@@ -244,14 +244,6 @@ class GuiPreferencesGeneral(QWidget):
|
|||||||
# ============
|
# ============
|
||||||
self.mainForm.addGroupLabel(self.tr("GUI Settings"))
|
self.mainForm.addGroupLabel(self.tr("GUI Settings"))
|
||||||
|
|
||||||
self.fullStatus = QSwitch()
|
|
||||||
self.fullStatus.setChecked(self.mainConf.fullStatus)
|
|
||||||
self.mainForm.addRow(
|
|
||||||
self.tr("Show status text in project tree"),
|
|
||||||
self.fullStatus,
|
|
||||||
self.tr("If disabled, only the icon is shown."),
|
|
||||||
)
|
|
||||||
|
|
||||||
self.emphLabels = QSwitch()
|
self.emphLabels = QSwitch()
|
||||||
self.emphLabels.setChecked(self.mainConf.emphLabels)
|
self.emphLabels.setChecked(self.mainConf.emphLabels)
|
||||||
self.mainForm.addRow(
|
self.mainForm.addRow(
|
||||||
@@ -295,7 +287,6 @@ class GuiPreferencesGeneral(QWidget):
|
|||||||
guiDark = self.guiDark.isChecked()
|
guiDark = self.guiDark.isChecked()
|
||||||
guiFont = self.guiFont.text()
|
guiFont = self.guiFont.text()
|
||||||
guiFontSize = self.guiFontSize.value()
|
guiFontSize = self.guiFontSize.value()
|
||||||
fullStatus = self.fullStatus.isChecked()
|
|
||||||
emphLabels = self.emphLabels.isChecked()
|
emphLabels = self.emphLabels.isChecked()
|
||||||
|
|
||||||
# Check if restart is needed
|
# Check if restart is needed
|
||||||
@@ -309,7 +300,6 @@ class GuiPreferencesGeneral(QWidget):
|
|||||||
|
|
||||||
# Check if refreshing project tree is needed
|
# Check if refreshing project tree is needed
|
||||||
refreshTree = False
|
refreshTree = False
|
||||||
refreshTree |= self.mainConf.fullStatus != fullStatus
|
|
||||||
refreshTree |= self.mainConf.emphLabels != emphLabels
|
refreshTree |= self.mainConf.emphLabels != emphLabels
|
||||||
|
|
||||||
self.mainConf.guiLang = guiLang
|
self.mainConf.guiLang = guiLang
|
||||||
@@ -318,7 +308,6 @@ class GuiPreferencesGeneral(QWidget):
|
|||||||
self.mainConf.guiDark = guiDark
|
self.mainConf.guiDark = guiDark
|
||||||
self.mainConf.guiFont = guiFont
|
self.mainConf.guiFont = guiFont
|
||||||
self.mainConf.guiFontSize = guiFontSize
|
self.mainConf.guiFontSize = guiFontSize
|
||||||
self.mainConf.fullStatus = fullStatus
|
|
||||||
self.mainConf.emphLabels = emphLabels
|
self.mainConf.emphLabels = emphLabels
|
||||||
self.mainConf.showFullPath = self.showFullPath.isChecked()
|
self.mainConf.showFullPath = self.showFullPath.isChecked()
|
||||||
self.mainConf.hideVScroll = self.hideVScroll.isChecked()
|
self.mainConf.hideVScroll = self.hideVScroll.isChecked()
|
||||||
@@ -758,6 +747,15 @@ class GuiPreferencesEditor(QWidget):
|
|||||||
theUnit=self.tr("seconds")
|
theUnit=self.tr("seconds")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Include Notes in Word Count
|
||||||
|
self.incNotesWCount = QSwitch()
|
||||||
|
self.incNotesWCount.setChecked(self.mainConf.incNotesWCount)
|
||||||
|
self.mainForm.addRow(
|
||||||
|
self.tr("Include project notes in total word count"),
|
||||||
|
self.incNotesWCount,
|
||||||
|
self.tr("Affects the word count shown on the status bar.")
|
||||||
|
)
|
||||||
|
|
||||||
# Writing Guides
|
# Writing Guides
|
||||||
# ==============
|
# ==============
|
||||||
self.mainForm.addGroupLabel(self.tr("Writing Guides"))
|
self.mainForm.addGroupLabel(self.tr("Writing Guides"))
|
||||||
@@ -826,6 +824,7 @@ class GuiPreferencesEditor(QWidget):
|
|||||||
|
|
||||||
# Word Count
|
# Word Count
|
||||||
self.mainConf.wordCountTimer = self.wordCountTimer.value()
|
self.mainConf.wordCountTimer = self.wordCountTimer.value()
|
||||||
|
self.mainConf.incNotesWCount = self.incNotesWCount.isChecked()
|
||||||
|
|
||||||
# Writing Guides
|
# Writing Guides
|
||||||
self.mainConf.showTabsNSpaces = self.showTabsNSpaces.isChecked()
|
self.mainConf.showTabsNSpaces = self.showTabsNSpaces.isChecked()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ novelWriter – GUI Updates
|
|||||||
A dialog box for checking for latest updates
|
A dialog box for checking for latest updates
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2021-08-21 [1.5-alpah0]
|
Created: 2021-08-21 [1.5a0]
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2021, Veronica Berglyd Olsen
|
Copyright 2018–2021, Veronica Berglyd Olsen
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ Created: 2018-09-29 [0.0.1] GuiDocEditor
|
|||||||
Created: 2019-04-22 [0.0.1] BackgroundWordCounter
|
Created: 2019-04-22 [0.0.1] BackgroundWordCounter
|
||||||
Created: 2019-09-29 [0.2.1] GuiDocEditSearch
|
Created: 2019-09-29 [0.2.1] GuiDocEditSearch
|
||||||
Created: 2020-04-25 [0.4.5] GuiDocEditHeader
|
Created: 2020-04-25 [0.4.5] GuiDocEditHeader
|
||||||
Rewritten: 2020-06-15 [0.9.0] GuiDocEditSearch
|
Rewritten: 2020-06-15 [0.9] GuiDocEditSearch
|
||||||
Created: 2020-06-27 [0.10.0] GuiDocEditFooter
|
Created: 2020-06-27 [0.10] GuiDocEditFooter
|
||||||
Rewritten: 2020-10-07 [1.0b3] BackgroundWordCounter
|
Rewritten: 2020-10-07 [1.0b3] BackgroundWordCounter
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ File History:
|
|||||||
Created: 2019-05-10 [0.0.1] GuiDocViewer
|
Created: 2019-05-10 [0.0.1] GuiDocViewer
|
||||||
Created: 2019-10-31 [0.3.2] GuiDocViewDetails
|
Created: 2019-10-31 [0.3.2] GuiDocViewDetails
|
||||||
Created: 2020-04-25 [0.4.5] GuiDocViewHeader
|
Created: 2020-04-25 [0.4.5] GuiDocViewHeader
|
||||||
Created: 2020-06-09 [0.8.0] GuiDocViewFooter
|
Created: 2020-06-09 [0.8] GuiDocViewFooter
|
||||||
Created: 2020-09-08 [1.0b1] GuiDocViewHistory
|
Created: 2020-09-08 [1.0b1] GuiDocViewHistory
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ GUI classes for the main window project tree
|
|||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
||||||
Created: 2020-06-04 [0.7.0] GuiProjectTreeMenu
|
Created: 2020-06-04 [0.7] GuiProjectTreeMenu
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2021, Veronica Berglyd Olsen
|
Copyright 2018–2021, Veronica Berglyd Olsen
|
||||||
@@ -51,7 +51,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
novelItemChanged = pyqtSignal()
|
novelItemChanged = pyqtSignal()
|
||||||
noteItemChanged = pyqtSignal()
|
noteItemChanged = pyqtSignal()
|
||||||
projectWordCountChanged = pyqtSignal(int, int)
|
wordCountsChanged = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, theParent):
|
def __init__(self, theParent):
|
||||||
QTreeWidget.__init__(self, theParent)
|
QTreeWidget.__init__(self, theParent)
|
||||||
@@ -86,8 +86,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.setIndentation(iPx)
|
self.setIndentation(iPx)
|
||||||
self.setColumnCount(4)
|
self.setColumnCount(4)
|
||||||
self.setHeaderLabels([
|
self.setHeaderLabels([
|
||||||
self.tr("Project Tree"), self.tr("Words"), "",
|
self.tr("Project Tree"), self.tr("Words"), "", ""
|
||||||
self.tr("Status") if self.mainConf.fullStatus else ""
|
|
||||||
])
|
])
|
||||||
|
|
||||||
treeHeadItem = self.headerItem()
|
treeHeadItem = self.headerItem()
|
||||||
@@ -305,7 +304,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
nwItem.setWordCount(wC)
|
nwItem.setWordCount(wC)
|
||||||
nwItem.setParaCount(pC)
|
nwItem.setParaCount(pC)
|
||||||
self.propagateCount(tHandle, wC)
|
self.propagateCount(tHandle, wC)
|
||||||
self.projectWordCount()
|
self.wordCountsChanged.emit()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -533,7 +532,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.theIndex.deleteHandle(tHandle)
|
self.theIndex.deleteHandle(tHandle)
|
||||||
self._deleteTreeItem(tHandle)
|
self._deleteTreeItem(tHandle)
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
self.projectWordCount()
|
self.wordCountsChanged.emit()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# The file is not already in the trash folder, so we
|
# The file is not already in the trash folder, so we
|
||||||
@@ -630,11 +629,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
trItem.setText(self.C_NAME, nwItem.itemName)
|
trItem.setText(self.C_NAME, nwItem.itemName)
|
||||||
trItem.setIcon(self.C_EXPORT, expIcon)
|
trItem.setIcon(self.C_EXPORT, expIcon)
|
||||||
trItem.setIcon(self.C_STATUS, statIcon)
|
trItem.setIcon(self.C_STATUS, statIcon)
|
||||||
|
trItem.setToolTip(self.C_STATUS, nwItem.itemStatus)
|
||||||
if self.mainConf.fullStatus:
|
|
||||||
trItem.setText(self.C_STATUS, nwItem.itemStatus)
|
|
||||||
else:
|
|
||||||
trItem.setToolTip(self.C_STATUS, nwItem.itemStatus)
|
|
||||||
|
|
||||||
if self.mainConf.emphLabels and nwItem.itemLayout == nwItemLayout.DOCUMENT:
|
if self.mainConf.emphLabels and nwItem.itemLayout == nwItemLayout.DOCUMENT:
|
||||||
if hLevel in ("H1", "H2"):
|
if hLevel in ("H1", "H2"):
|
||||||
@@ -674,25 +669,6 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def projectWordCount(self):
|
|
||||||
"""Sum up the word counts for all root items and set the
|
|
||||||
relevant values in the project and on the status bar. This call
|
|
||||||
is a fast way of getting this number, and depends on the
|
|
||||||
propagateCount function being called when it should to maintain
|
|
||||||
the correct count.
|
|
||||||
"""
|
|
||||||
nWords = 0
|
|
||||||
for n in range(self.topLevelItemCount()):
|
|
||||||
tItem = self.topLevelItem(n)
|
|
||||||
nWords += int(tItem.data(self.C_COUNT, Qt.UserRole))
|
|
||||||
|
|
||||||
self.theProject.setProjectWordCount(nWords)
|
|
||||||
sWords = self.theProject.getSessionWordCount()
|
|
||||||
|
|
||||||
self.projectWordCountChanged.emit(nWords, sWords)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def buildTree(self):
|
def buildTree(self):
|
||||||
"""Build the entire project tree from scratch. This depends on
|
"""Build the entire project tree from scratch. This depends on
|
||||||
the save project item iterator in the project class which will
|
the save project item iterator in the project class which will
|
||||||
@@ -702,11 +678,6 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
logger.debug("Building the project tree ...")
|
logger.debug("Building the project tree ...")
|
||||||
self.clearTree()
|
self.clearTree()
|
||||||
|
|
||||||
self.setHeaderLabels([
|
|
||||||
self.tr("Project Tree"), self.tr("Words"), "",
|
|
||||||
self.tr("Status") if self.mainConf.fullStatus else ""
|
|
||||||
])
|
|
||||||
|
|
||||||
iCount = 0
|
iCount = 0
|
||||||
for nwItem in self.theProject.getProjectItems():
|
for nwItem in self.theProject.getProjectItems():
|
||||||
iCount += 1
|
iCount += 1
|
||||||
@@ -819,7 +790,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
"""Slot for updating the word count of a specific item.
|
"""Slot for updating the word count of a specific item.
|
||||||
"""
|
"""
|
||||||
self.propagateCount(tHandle, wCount)
|
self.propagateCount(tHandle, wCount)
|
||||||
self.projectWordCount()
|
self.wordCountsChanged.emit()
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ novelWriter – GUI Main Window Status Bar
|
|||||||
GUI class for the main window status bar
|
GUI class for the main window status bar
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-04-20 [0.0.1]
|
Created: 2019-04-20 [0.0.1] GuiMainStatus
|
||||||
|
Created: 2020-05-17 [0.5.1] StatusLED
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2021, Veronica Berglyd Olsen
|
Copyright 2018–2021, Veronica Berglyd Olsen
|
||||||
@@ -28,7 +29,7 @@ import novelwriter
|
|||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from PyQt5.QtCore import QLocale, pyqtSlot
|
from PyQt5.QtCore import pyqtSlot, QLocale
|
||||||
from PyQt5.QtGui import QColor, QPainter
|
from PyQt5.QtGui import QColor, QPainter
|
||||||
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
|
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ class GuiMainStatus(QStatusBar):
|
|||||||
"""
|
"""
|
||||||
self.setRefTime(None)
|
self.setRefTime(None)
|
||||||
self.setLanguage(None, "")
|
self.setLanguage(None, "")
|
||||||
self.doUpdateProjectStats(0, 0)
|
self.setProjectStats(0, 0)
|
||||||
self.setProjectStatus(nwState.NONE)
|
self.setProjectStatus(nwState.NONE)
|
||||||
self.setDocumentStatus(nwState.NONE)
|
self.setDocumentStatus(nwState.NONE)
|
||||||
self.updateTime()
|
self.updateTime()
|
||||||
@@ -176,6 +177,16 @@ class GuiMainStatus(QStatusBar):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def setProjectStats(self, pWC, sWC):
|
||||||
|
"""Update the current project statistics.
|
||||||
|
"""
|
||||||
|
self.statsText.setText(self.tr("Words: {0} ({1})").format(f"{pWC:n}", f"{sWC:+n}"))
|
||||||
|
if self.mainConf.incNotesWCount:
|
||||||
|
self.statsText.setToolTip(self.tr("Project word count (session change)"))
|
||||||
|
else:
|
||||||
|
self.statsText.setToolTip(self.tr("Novel word count (session change)"))
|
||||||
|
return
|
||||||
|
|
||||||
def updateTime(self, idleTime=0.0):
|
def updateTime(self, idleTime=0.0):
|
||||||
"""Update the session clock.
|
"""Update the session clock.
|
||||||
"""
|
"""
|
||||||
@@ -211,14 +222,6 @@ class GuiMainStatus(QStatusBar):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(int, int)
|
|
||||||
def doUpdateProjectStats(self, pWC, sWC):
|
|
||||||
"""Update the current project statistics.
|
|
||||||
"""
|
|
||||||
self.statsText.setText(self.tr("Words: {0} ({1})").format(f"{pWC:n}", f"{sWC:+n}"))
|
|
||||||
self.statsText.setToolTip(self.tr("Project word count (session change)"))
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
@pyqtSlot(bool)
|
||||||
def doUpdateProjectStatus(self, isChanged):
|
def doUpdateProjectStatus(self, isChanged):
|
||||||
"""Slot for updating the project status.
|
"""Slot for updating the project status.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Classes managing and caching themes and icons
|
|||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-05-18 [0.1.3] GuiTheme
|
Created: 2019-05-18 [0.1.3] GuiTheme
|
||||||
Created: 2019-11-08 [0.4.0] GuiIcons
|
Created: 2019-11-08 [0.4] GuiIcons
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2021, Veronica Berglyd Olsen
|
Copyright 2018–2021, Veronica Berglyd Olsen
|
||||||
|
|||||||
+24
-3
@@ -124,7 +124,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
|
self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
|
||||||
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
|
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
|
||||||
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
|
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
|
||||||
self.treeView.projectWordCountChanged.connect(self.statusBar.doUpdateProjectStats)
|
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
|
||||||
|
|
||||||
# Minor GUI Elements
|
# Minor GUI Elements
|
||||||
self.statusIcons = []
|
self.statusIcons = []
|
||||||
@@ -529,7 +529,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
|
self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
|
||||||
self.mainMenu.setAutoOutline(self.theProject.autoOutline)
|
self.mainMenu.setAutoOutline(self.theProject.autoOutline)
|
||||||
self.statusBar.setRefTime(self.theProject.projOpened)
|
self.statusBar.setRefTime(self.theProject.projOpened)
|
||||||
self.statusBar.doUpdateProjectStats(self.theProject.currWCount, 0)
|
self._updateStatusWordCount()
|
||||||
|
|
||||||
# Restore previously open documents, if any
|
# Restore previously open documents, if any
|
||||||
if self.theProject.lastEdited is not None:
|
if self.theProject.lastEdited is not None:
|
||||||
@@ -903,13 +903,13 @@ class GuiMain(QMainWindow):
|
|||||||
tItem.setParaCount(pC)
|
tItem.setParaCount(pC)
|
||||||
self.treeView.propagateCount(tItem.itemHandle, wC)
|
self.treeView.propagateCount(tItem.itemHandle, wC)
|
||||||
self.treeView.setTreeItemValues(tItem.itemHandle)
|
self.treeView.setTreeItemValues(tItem.itemHandle)
|
||||||
self.treeView.projectWordCount()
|
|
||||||
|
|
||||||
tEnd = time()
|
tEnd = time()
|
||||||
self.setStatus(
|
self.setStatus(
|
||||||
self.tr("Indexing completed in {0} ms").format(f"{(tEnd - tStart)*1000.0:.1f}")
|
self.tr("Indexing completed in {0} ms").format(f"{(tEnd - tStart)*1000.0:.1f}")
|
||||||
)
|
)
|
||||||
self.docEditor.updateTagHighLighting()
|
self.docEditor.updateTagHighLighting()
|
||||||
|
self._updateStatusWordCount()
|
||||||
qApp.restoreOverrideCursor()
|
qApp.restoreOverrideCursor()
|
||||||
|
|
||||||
if not beQuiet:
|
if not beQuiet:
|
||||||
@@ -980,6 +980,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.novelView.initTree()
|
self.novelView.initTree()
|
||||||
self.projView.initOutline()
|
self.projView.initOutline()
|
||||||
self.projMeta.initDetails()
|
self.projMeta.initDetails()
|
||||||
|
self._updateStatusWordCount()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1527,6 +1528,26 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def _updateStatusWordCount(self):
|
||||||
|
"""Update the word count on the status bar.
|
||||||
|
"""
|
||||||
|
if not self.hasProject:
|
||||||
|
self.statusBar.setProjectStats(0, 0)
|
||||||
|
|
||||||
|
logger.verbose("Updating total word count")
|
||||||
|
self.theProject.updateWordCounts()
|
||||||
|
if self.mainConf.incNotesWCount:
|
||||||
|
currWords = self.theProject.currWCount
|
||||||
|
diffWords = currWords - self.theProject.lastWCount
|
||||||
|
else:
|
||||||
|
currWords = self.theProject.currNovelWC
|
||||||
|
diffWords = currWords - self.theProject.lastNovelWC
|
||||||
|
|
||||||
|
self.statusBar.setProjectStats(currWords, diffWords)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _treeSingleClick(self):
|
def _treeSingleClick(self):
|
||||||
"""Single click on a project tree item just updates the details
|
"""Single click on a project tree item just updates the details
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Main]
|
[Main]
|
||||||
timestamp = 2021-08-30 21:27:27
|
timestamp = 2021-09-10 00:23:50
|
||||||
theme = default
|
theme = default
|
||||||
syntax = default_light
|
syntax = default_light
|
||||||
icons = typicons_light
|
icons = typicons_light
|
||||||
@@ -26,7 +26,6 @@ fullscreen = False
|
|||||||
[Project]
|
[Project]
|
||||||
autosaveproject = 60
|
autosaveproject = 60
|
||||||
autosavedoc = 30
|
autosavedoc = 30
|
||||||
fullstatus = True
|
|
||||||
emphlabels = True
|
emphlabels = True
|
||||||
|
|
||||||
[Editor]
|
[Editor]
|
||||||
@@ -57,7 +56,9 @@ spellcheck = en
|
|||||||
showtabsnspaces = False
|
showtabsnspaces = False
|
||||||
showlineendings = False
|
showlineendings = False
|
||||||
showmultispaces = True
|
showmultispaces = True
|
||||||
|
wordcounttimer = 5.0
|
||||||
bigdoclimit = 800
|
bigdoclimit = 800
|
||||||
|
incnoteswcount = True
|
||||||
showfullpath = True
|
showfullpath = True
|
||||||
highlightquotes = True
|
highlightquotes = True
|
||||||
allowopensquote = False
|
allowopensquote = False
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Main]
|
[Main]
|
||||||
timestamp = 2021-08-30 21:45:17
|
timestamp = 2021-09-10 00:23:52
|
||||||
theme = default
|
theme = default
|
||||||
syntax = default_light
|
syntax = default_light
|
||||||
icons = typicons_light
|
icons = typicons_light
|
||||||
@@ -26,7 +26,6 @@ fullscreen = False
|
|||||||
[Project]
|
[Project]
|
||||||
autosaveproject = 40
|
autosaveproject = 40
|
||||||
autosavedoc = 20
|
autosavedoc = 20
|
||||||
fullstatus = True
|
|
||||||
emphlabels = True
|
emphlabels = True
|
||||||
|
|
||||||
[Editor]
|
[Editor]
|
||||||
@@ -57,7 +56,9 @@ spellcheck = en
|
|||||||
showtabsnspaces = True
|
showtabsnspaces = True
|
||||||
showlineendings = True
|
showlineendings = True
|
||||||
showmultispaces = True
|
showmultispaces = True
|
||||||
|
wordcounttimer = 5.0
|
||||||
bigdoclimit = 500
|
bigdoclimit = 500
|
||||||
|
incnoteswcount = True
|
||||||
showfullpath = False
|
showfullpath = False
|
||||||
highlightquotes = False
|
highlightquotes = False
|
||||||
allowopensquote = False
|
allowopensquote = False
|
||||||
|
|||||||
@@ -482,6 +482,7 @@ def testBaseCommon_NWConfigParser(fncDir):
|
|||||||
"boolopt4 = 0\n"
|
"boolopt4 = 0\n"
|
||||||
"list1 = a, b, c\n"
|
"list1 = a, b, c\n"
|
||||||
"list2 = 17, 18, 19\n"
|
"list2 = 17, 18, 19\n"
|
||||||
|
"float1 = 4.2\n"
|
||||||
))
|
))
|
||||||
|
|
||||||
cfgParser = NWConfigParser()
|
cfgParser = NWConfigParser()
|
||||||
@@ -516,6 +517,14 @@ def testBaseCommon_NWConfigParser(fncDir):
|
|||||||
assert cfgParser.rdInt("nope", "intopt1", 13) == 13
|
assert cfgParser.rdInt("nope", "intopt1", 13) == 13
|
||||||
assert cfgParser.rdInt("main", "blabla", 13) == 13
|
assert cfgParser.rdInt("main", "blabla", 13) == 13
|
||||||
|
|
||||||
|
# Read Float
|
||||||
|
assert cfgParser.rdFlt("main", "intopt1", 13.0) == 42.0
|
||||||
|
assert cfgParser.rdFlt("main", "float1", 13.0) == 4.2
|
||||||
|
assert cfgParser.rdInt("main", "stropt", 13.0) == 13.0
|
||||||
|
|
||||||
|
assert cfgParser.rdInt("nope", "intopt1", 13.0) == 13.0
|
||||||
|
assert cfgParser.rdInt("main", "blabla", 13.0) == 13.0
|
||||||
|
|
||||||
# Read String List
|
# Read String List
|
||||||
assert cfgParser.rdStrList("main", "list1", []) == []
|
assert cfgParser.rdStrList("main", "list1", []) == []
|
||||||
assert cfgParser.rdStrList("main", "list1", ["x"]) == ["a"]
|
assert cfgParser.rdStrList("main", "list1", ["x"]) == ["a"]
|
||||||
|
|||||||
@@ -519,24 +519,24 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir):
|
|||||||
# Flag Setters
|
# Flag Setters
|
||||||
# ============
|
# ============
|
||||||
|
|
||||||
assert not tmpConf.setShowRefPanel(False)
|
assert tmpConf.setShowRefPanel(False) is False
|
||||||
assert not tmpConf.showRefPanel
|
assert tmpConf.showRefPanel is False
|
||||||
assert tmpConf.setShowRefPanel(True)
|
assert tmpConf.setShowRefPanel(True) is True
|
||||||
|
|
||||||
assert not tmpConf.setViewComments(False)
|
assert tmpConf.setViewComments(False) is False
|
||||||
assert not tmpConf.viewComments
|
assert tmpConf.viewComments is False
|
||||||
assert tmpConf.setViewComments(True)
|
assert tmpConf.setViewComments(True) is True
|
||||||
|
|
||||||
assert not tmpConf.setViewSynopsis(False)
|
assert tmpConf.setViewSynopsis(False) is False
|
||||||
assert not tmpConf.viewSynopsis
|
assert tmpConf.viewSynopsis is False
|
||||||
assert tmpConf.setViewSynopsis(True)
|
assert tmpConf.setViewSynopsis(True) is True
|
||||||
|
|
||||||
# Check Final File
|
# Check Final File
|
||||||
# ================
|
# ================
|
||||||
|
|
||||||
assert tmpConf.confChanged
|
assert tmpConf.confChanged is True
|
||||||
assert tmpConf.saveConfig()
|
assert tmpConf.saveConfig() is True
|
||||||
assert not tmpConf.confChanged
|
assert tmpConf.confChanged is False
|
||||||
|
|
||||||
copyfile(confFile, testFile)
|
copyfile(confFile, testFile)
|
||||||
assert cmpFiles(testFile, compFile, [2, 9, 10])
|
assert cmpFiles(testFile, compFile, [2, 9, 10])
|
||||||
|
|||||||
@@ -868,12 +868,9 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
|
|||||||
assert theProject.statusItems._theCounts == [1, 1, 1, 2, 0]
|
assert theProject.statusItems._theCounts == [1, 1, 1, 2, 0]
|
||||||
assert theProject.importItems._theCounts == [3, 0, 0, 1, 0]
|
assert theProject.importItems._theCounts == [3, 0, 0, 1, 0]
|
||||||
|
|
||||||
# Check word counts
|
# Session stats
|
||||||
theProject.currWCount = 200
|
theProject.currWCount = 200
|
||||||
theProject.lastWCount = 100
|
theProject.lastWCount = 100
|
||||||
assert theProject.getSessionWordCount() == 100
|
|
||||||
|
|
||||||
# Session stats
|
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("os.path.isdir", lambda *a, **k: False)
|
mp.setattr("os.path.isdir", lambda *a, **k: False)
|
||||||
assert not theProject._appendSessionStats(idleTime=0)
|
assert not theProject._appendSessionStats(idleTime=0)
|
||||||
@@ -888,8 +885,8 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
|
|||||||
statsFile = os.path.join(theProject.projMeta, nwFiles.SESS_STATS)
|
statsFile = os.path.join(theProject.projMeta, nwFiles.SESS_STATS)
|
||||||
|
|
||||||
theProject.projOpened = 1600002000
|
theProject.projOpened = 1600002000
|
||||||
theProject.novelWCount = 200
|
theProject.currNovelWC = 200
|
||||||
theProject.notesWCount = 100
|
theProject.currNotesWC = 100
|
||||||
|
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("novelwriter.core.project.time", lambda: 1600005600)
|
mp.setattr("novelwriter.core.project.time", lambda: 1600005600)
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
|
|||||||
testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf")
|
testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf")
|
||||||
compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf")
|
compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf")
|
||||||
copyfile(projFile, testFile)
|
copyfile(projFile, testFile)
|
||||||
ignoreLines = [2, 7, 9, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 33, 34]
|
ignoreLines = [2, 7, 9, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 32, 33]
|
||||||
assert cmpFiles(testFile, compFile, ignoreLines)
|
assert cmpFiles(testFile, compFile, ignoreLines)
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
"""
|
||||||
|
novelWriter – Main Status Bar Class Tester
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
This file is a part of novelWriter
|
||||||
|
Copyright 2018–2021, Veronica Berglyd Olsen
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import QMessageBox
|
||||||
|
|
||||||
|
from novelwriter.core import NWDoc
|
||||||
|
from novelwriter.enum import nwItemClass, nwState
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.gui
|
||||||
|
def testGuiStatusBar_Main(qtbot, monkeypatch, nwGUI, fncProj):
|
||||||
|
"""Test the the various features of the status bar.
|
||||||
|
"""
|
||||||
|
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
|
||||||
|
|
||||||
|
nwGUI.theProject.projTree.setSeed(42)
|
||||||
|
assert nwGUI.newProject({"projPath": fncProj}) is True
|
||||||
|
cHandle = nwGUI.theProject.newFile("A Note", nwItemClass.CHARACTER, "71ee45a3c0db9")
|
||||||
|
newDoc = NWDoc(nwGUI.theProject, cHandle)
|
||||||
|
newDoc.writeDocument("# A Note\n\n")
|
||||||
|
nwGUI.treeView.revealNewTreeItem(cHandle)
|
||||||
|
nwGUI.rebuildIndex(beQuiet=True)
|
||||||
|
|
||||||
|
# Reference Time
|
||||||
|
refTime = time.time()
|
||||||
|
nwGUI.statusBar.setRefTime(refTime)
|
||||||
|
assert nwGUI.statusBar.refTime == refTime
|
||||||
|
|
||||||
|
# Project Status
|
||||||
|
nwGUI.statusBar.setProjectStatus(nwState.NONE)
|
||||||
|
assert nwGUI.statusBar.projIcon._theCol == nwGUI.statusBar.projIcon._colNone
|
||||||
|
nwGUI.statusBar.setProjectStatus(nwState.BAD)
|
||||||
|
assert nwGUI.statusBar.projIcon._theCol == nwGUI.statusBar.projIcon._colBad
|
||||||
|
nwGUI.statusBar.setProjectStatus(nwState.GOOD)
|
||||||
|
assert nwGUI.statusBar.projIcon._theCol == nwGUI.statusBar.projIcon._colGood
|
||||||
|
|
||||||
|
# Document Status
|
||||||
|
nwGUI.statusBar.setDocumentStatus(nwState.NONE)
|
||||||
|
assert nwGUI.statusBar.docIcon._theCol == nwGUI.statusBar.docIcon._colNone
|
||||||
|
nwGUI.statusBar.setDocumentStatus(nwState.BAD)
|
||||||
|
assert nwGUI.statusBar.docIcon._theCol == nwGUI.statusBar.docIcon._colBad
|
||||||
|
nwGUI.statusBar.setDocumentStatus(nwState.GOOD)
|
||||||
|
assert nwGUI.statusBar.docIcon._theCol == nwGUI.statusBar.docIcon._colGood
|
||||||
|
|
||||||
|
# Idle Status
|
||||||
|
nwGUI.statusBar.mainConf.stopWhenIdle = False
|
||||||
|
nwGUI.statusBar.setUserIdle(True)
|
||||||
|
nwGUI.statusBar.updateTime()
|
||||||
|
assert nwGUI.statusBar.userIdle is False
|
||||||
|
assert nwGUI.statusBar.timeText.text() == "00:00:00"
|
||||||
|
|
||||||
|
nwGUI.statusBar.mainConf.stopWhenIdle = True
|
||||||
|
nwGUI.statusBar.setUserIdle(True)
|
||||||
|
nwGUI.statusBar.updateTime(5)
|
||||||
|
assert nwGUI.statusBar.userIdle is True
|
||||||
|
assert nwGUI.statusBar.timeText.text() != "00:00:00"
|
||||||
|
|
||||||
|
nwGUI.statusBar.setUserIdle(False)
|
||||||
|
nwGUI.statusBar.updateTime(5)
|
||||||
|
assert nwGUI.statusBar.userIdle is False
|
||||||
|
assert nwGUI.statusBar.timeText.text() != "00:00:00"
|
||||||
|
|
||||||
|
# Language
|
||||||
|
nwGUI.statusBar.setLanguage("None", "None")
|
||||||
|
assert nwGUI.statusBar.langText.text() == "None"
|
||||||
|
nwGUI.statusBar.setLanguage("en", "None")
|
||||||
|
assert nwGUI.statusBar.langText.text() == "American English"
|
||||||
|
|
||||||
|
# Project Stats
|
||||||
|
nwGUI.statusBar.mainConf.incNotesWCount = False
|
||||||
|
nwGUI._updateStatusWordCount()
|
||||||
|
assert nwGUI.statusBar.statsText.text() == "Words: 6 (+6)"
|
||||||
|
nwGUI.statusBar.mainConf.incNotesWCount = True
|
||||||
|
nwGUI._updateStatusWordCount()
|
||||||
|
assert nwGUI.statusBar.statsText.text() == "Words: 8 (+8)"
|
||||||
|
|
||||||
|
# qtbot.stopForInteraction()
|
||||||
|
|
||||||
|
# END Test testGuiStatusBar_Init
|
||||||
Reference in New Issue
Block a user