Skip to content

Commit 3c8cb34

Browse files
authored
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
1 parent b9311e8 commit 3c8cb34

File tree

19 files changed

+246
-134
lines changed

19 files changed

+246
-134
lines changed

novelwriter/common.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Various common functions
55
66
File History:
7-
Created: 2019-05-12 [0.1.0]
7+
Created: 2019-05-12 [0.1]
88
99
This file is a part of novelWriter
1010
Copyright 2018–2021, Veronica Berglyd Olsen
@@ -441,9 +441,10 @@ class NWConfigParser(ConfigParser):
441441

442442
CNF_STR = 0
443443
CNF_INT = 1
444-
CNF_BOOL = 2
445-
CNF_S_LST = 3
446-
CNF_I_LST = 4
444+
CNF_FLOAT = 2
445+
CNF_BOOL = 3
446+
CNF_S_LST = 4
447+
CNF_I_LST = 5
447448

448449
def __init__(self):
449450
super().__init__()
@@ -458,6 +459,11 @@ def rdInt(self, section, option, default):
458459
"""
459460
return self._parseLine(section, option, default, self.CNF_INT)
460461

462+
def rdFlt(self, section, option, default):
463+
"""Read float value.
464+
"""
465+
return self._parseLine(section, option, default, self.CNF_FLOAT)
466+
461467
def rdBool(self, section, option, default):
462468
"""Read boolean value.
463469
"""
@@ -503,6 +509,8 @@ def _parseLine(self, section, option, default, type):
503509
return self.get(section, option)
504510
elif type == self.CNF_INT:
505511
return self.getint(section, option)
512+
elif type == self.CNF_FLOAT:
513+
return self.getfloat(section, option)
506514
elif type == self.CNF_BOOL:
507515
return self.getboolean(section, option)
508516
elif type in (self.CNF_I_LST, self.CNF_S_LST):

novelwriter/config.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ def __init__(self):
108108
# Features
109109
self.hideVScroll = False # Hide vertical scroll bars on main widgets
110110
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
111-
self.fullStatus = True # Show the full status text in the project tree
112111
self.emphLabels = True # Add emphasis to H1 and H2 item labels
113112

114113
# Project
@@ -145,6 +144,7 @@ def __init__(self):
145144

146145
self.wordCountTimer = 5.0 # Interval for word count update in seconds
147146
self.bigDocLimit = 800 # Size threshold for heavy editor features in kilobytes
147+
self.incNotesWCount = True # The status bar word count includes notes
148148

149149
self.highlightQuotes = True # Highlight text in quotes
150150
self.allowOpenSQuote = False # Allow open-ended single quotes
@@ -179,9 +179,9 @@ def __init__(self):
179179
self.askBeforeBackup = True
180180

181181
# State
182-
self.showRefPanel = True
183-
self.viewComments = True
184-
self.viewSynopsis = True
182+
self.showRefPanel = True # The reference panel for the viewer is visible
183+
self.viewComments = True # Comments are shown in the viewer
184+
self.viewSynopsis = True # Synopsis is shown in the viewer
185185

186186
# Check Qt5 Versions
187187
verQt = splitVersionNumber(QT_VERSION_STR)
@@ -466,7 +466,6 @@ def loadConfig(self):
466466
cnfSec = "Project"
467467
self.autoSaveProj = theConf.rdInt(cnfSec, "autosaveproject", self.autoSaveProj)
468468
self.autoSaveDoc = theConf.rdInt(cnfSec, "autosavedoc", self.autoSaveDoc)
469-
self.fullStatus = theConf.rdBool(cnfSec, "fullstatus", self.fullStatus)
470469
self.emphLabels = theConf.rdBool(cnfSec, "emphlabels", self.emphLabels)
471470

472471
# Editor
@@ -498,7 +497,9 @@ def loadConfig(self):
498497
self.showTabsNSpaces = theConf.rdBool(cnfSec, "showtabsnspaces", self.showTabsNSpaces)
499498
self.showLineEndings = theConf.rdBool(cnfSec, "showlineendings", self.showLineEndings)
500499
self.showMultiSpaces = theConf.rdBool(cnfSec, "showmultispaces", self.showMultiSpaces)
500+
self.wordCountTimer = theConf.rdFlt(cnfSec, "wordcounttimer", self.wordCountTimer)
501501
self.bigDocLimit = theConf.rdInt(cnfSec, "bigdoclimit", self.bigDocLimit)
502+
self.incNotesWCount = theConf.rdBool(cnfSec, "incnoteswcount", self.incNotesWCount)
502503
self.showFullPath = theConf.rdBool(cnfSec, "showfullpath", self.showFullPath)
503504
self.highlightQuotes = theConf.rdBool(cnfSec, "highlightquotes", self.highlightQuotes)
504505
self.allowOpenSQuote = theConf.rdBool(cnfSec, "allowopensquote", self.allowOpenSQuote)
@@ -588,7 +589,6 @@ def saveConfig(self):
588589
theConf["Project"] = {
589590
"autosaveproject": str(self.autoSaveProj),
590591
"autosavedoc": str(self.autoSaveDoc),
591-
"fullstatus": str(self.fullStatus),
592592
"emphlabels": str(self.emphLabels),
593593
}
594594

@@ -620,7 +620,9 @@ def saveConfig(self):
620620
"showtabsnspaces": str(self.showTabsNSpaces),
621621
"showlineendings": str(self.showLineEndings),
622622
"showmultispaces": str(self.showMultiSpaces),
623+
"wordcounttimer": str(self.wordCountTimer),
623624
"bigdoclimit": str(self.bigDocLimit),
625+
"incnoteswcount": str(self.incNotesWCount),
624626
"showfullpath": str(self.showFullPath),
625627
"highlightquotes": str(self.highlightQuotes),
626628
"allowopensquote": str(self.allowOpenSQuote),
@@ -821,7 +823,7 @@ def setMainPanePos(self, panePos):
821823
return True
822824

823825
def setDocPanePos(self, panePos):
824-
self.docPanePos = [int(x/self.guiScale) for x in panePos]
826+
self.docPanePos = [int(x/self.guiScale) for x in panePos]
825827
self.confChanged = True
826828
return True
827829

@@ -832,22 +834,22 @@ def setViewPanePos(self, panePos):
832834

833835
def setOutlinePanePos(self, panePos):
834836
self.outlnPanePos = [int(x/self.guiScale) for x in panePos]
835-
self.confChanged = True
837+
self.confChanged = True
836838
return True
837839

838840
def setShowRefPanel(self, checkState):
839841
self.showRefPanel = checkState
840-
self.confChanged = True
842+
self.confChanged = True
841843
return self.showRefPanel
842844

843845
def setViewComments(self, viewState):
844846
self.viewComments = viewState
845-
self.confChanged = True
847+
self.confChanged = True
846848
return self.viewComments
847849

848850
def setViewSynopsis(self, viewState):
849851
self.viewSynopsis = viewState
850-
self.confChanged = True
852+
self.confChanged = True
851853
return self.viewSynopsis
852854

853855
##

novelwriter/core/project.py

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,11 @@ def __init__(self, theParent):
9999
self.lastEdited = None # The handle of the last file to be edited
100100
self.lastViewed = None # The handle of the last file to be viewed
101101
self.lastWCount = 0 # The project word count from last session
102+
self.lastNovelWC = 0 # The novel files word count from last session
103+
self.lastNotesWC = 0 # The note files word count from last session
102104
self.currWCount = 0 # The project word count in current session
103-
self.novelWCount = 0 # Total number of words in novel files
104-
self.notesWCount = 0 # Total number of words in note files
105+
self.currNovelWC = 0 # The novel files word count in cutrent session
106+
self.currNotesWC = 0 # The note files word count in cutrent session
105107
self.doBackup = True # Run project backup on exit
106108

107109
# Internal Mapping
@@ -226,9 +228,11 @@ def clearProject(self):
226228
self.lastEdited = None
227229
self.lastViewed = None
228230
self.lastWCount = 0
231+
self.lastNovelWC = 0
232+
self.lastNotesWC = 0
229233
self.currWCount = 0
230-
self.novelWCount = 0
231-
self.notesWCount = 0
234+
self.currNovelWC = 0
235+
self.currNotesWC = 0
232236

233237
return
234238

@@ -566,9 +570,9 @@ def openProject(self, fileName, overrideLock=False):
566570
elif xItem.tag == "lastWordCount":
567571
self.lastWCount = checkInt(xItem.text, 0, False)
568572
elif xItem.tag == "novelWordCount":
569-
self.novelWCount = checkInt(xItem.text, 0, False)
573+
self.lastNovelWC = checkInt(xItem.text, 0, False)
570574
elif xItem.tag == "notesWordCount":
571-
self.notesWCount = checkInt(xItem.text, 0, False)
575+
self.lastNotesWC = checkInt(xItem.text, 0, False)
572576
elif xItem.tag == "status":
573577
self.statusItems.unpackXML(xItem)
574578
elif xItem.tag == "importance":
@@ -610,8 +614,8 @@ def openProject(self, fileName, overrideLock=False):
610614

611615
self._scanProjectFolder()
612616
self._loadProjectLocalisation()
617+
self.updateWordCounts()
613618

614-
self.currWCount = self.lastWCount
615619
self.projOpened = time()
616620
self.projAltered = False
617621

@@ -652,11 +656,8 @@ def saveProject(self, autoSave=False):
652656
"timeStamp": formatTimeStamp(saveTime),
653657
})
654658

659+
self.updateWordCounts()
655660
editTime = int(self.editTime + saveTime - self.projOpened)
656-
wcNovel, wcNotes = self.projTree.sumWords()
657-
self.novelWCount = wcNovel
658-
self.notesWCount = wcNotes
659-
self.setProjectWordCount(wcNovel + wcNotes)
660661

661662
# Save Project Meta
662663
xProject = etree.SubElement(nwXML, "project")
@@ -677,8 +678,8 @@ def saveProject(self, autoSave=False):
677678
self._packProjectValue(xSettings, "lastEdited", self.lastEdited)
678679
self._packProjectValue(xSettings, "lastViewed", self.lastViewed)
679680
self._packProjectValue(xSettings, "lastWordCount", self.currWCount)
680-
self._packProjectValue(xSettings, "novelWordCount", wcNovel)
681-
self._packProjectValue(xSettings, "notesWordCount", wcNotes)
681+
self._packProjectValue(xSettings, "novelWordCount", self.currNovelWC)
682+
self._packProjectValue(xSettings, "notesWordCount", self.currNotesWC)
682683
self._packProjectKeyValue(xSettings, "autoReplace", self.autoReplace)
683684

684685
xTitleFmt = etree.SubElement(xSettings, "titleFormat")
@@ -1067,14 +1068,6 @@ def setLastViewed(self, tHandle):
10671068
self.setProjectChanged(True)
10681069
return True
10691070

1070-
def setProjectWordCount(self, theCount):
1071-
"""Set the current project word count.
1072-
"""
1073-
if self.currWCount != theCount:
1074-
self.currWCount = theCount
1075-
self.setProjectChanged(True)
1076-
return True
1077-
10781071
def setStatusColours(self, newCols):
10791072
"""Update the list of novel file status flags. Also iterate
10801073
through the project and replace keys that have been renamed.
@@ -1145,11 +1138,6 @@ def getAuthors(self):
11451138

11461139
return authString
11471140

1148-
def getSessionWordCount(self):
1149-
"""Returns the number of words added or removed this session.
1150-
"""
1151-
return self.currWCount - self.lastWCount
1152-
11531141
def getCurrentEditTime(self):
11541142
"""Get the total project edit time, including the time spent in
11551143
the current session.
@@ -1202,6 +1190,18 @@ def getProjectItems(self):
12021190
# Class Methods
12031191
##
12041192

1193+
def updateWordCounts(self):
1194+
"""Update the total word count values.
1195+
"""
1196+
wcNovel, wcNotes = self.projTree.sumWords()
1197+
wcTotal = wcNovel + wcNotes
1198+
if wcTotal != self.currWCount:
1199+
self.currNovelWC = wcNovel
1200+
self.currNotesWC = wcNotes
1201+
self.currWCount = wcTotal
1202+
self.setProjectChanged(True)
1203+
return
1204+
12051205
def countStatus(self):
12061206
"""Count how many times the various status flags are used in the
12071207
project tree. The counts themselves are kept in the NWStatus
@@ -1460,7 +1460,7 @@ def _appendSessionStats(self, idleTime):
14601460
isFile = os.path.isfile(sessionFile)
14611461

14621462
nowTime = time()
1463-
sessDiff = self.getSessionWordCount()
1463+
sessDiff = self.currWCount - self.lastWCount
14641464
sessTime = nowTime - self.projOpened
14651465

14661466
logger.info("The session lasted %d sec and added %d words", int(sessTime), sessDiff)
@@ -1481,8 +1481,8 @@ def _appendSessionStats(self, idleTime):
14811481
outFile.write("%-19s %-19s %8d %8d %8d\n" % (
14821482
formatTimeStamp(self.projOpened),
14831483
formatTimeStamp(nowTime),
1484-
self.novelWCount,
1485-
self.notesWCount,
1484+
self.currNovelWC,
1485+
self.currNotesWC,
14861486
int(idleTime),
14871487
))
14881488

novelwriter/core/tree.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def writeToCFile(self):
190190
return True
191191

192192
def sumWords(self):
193-
"""Loops over all entries and adds up the word counts.
193+
"""Loop over all entries and add up the word counts.
194194
"""
195195
noteWords = 0
196196
novelWords = 0

novelwriter/dialogs/preferences.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -244,14 +244,6 @@ def __init__(self, theParent):
244244
# ============
245245
self.mainForm.addGroupLabel(self.tr("GUI Settings"))
246246

247-
self.fullStatus = QSwitch()
248-
self.fullStatus.setChecked(self.mainConf.fullStatus)
249-
self.mainForm.addRow(
250-
self.tr("Show status text in project tree"),
251-
self.fullStatus,
252-
self.tr("If disabled, only the icon is shown."),
253-
)
254-
255247
self.emphLabels = QSwitch()
256248
self.emphLabels.setChecked(self.mainConf.emphLabels)
257249
self.mainForm.addRow(
@@ -295,7 +287,6 @@ def saveValues(self):
295287
guiDark = self.guiDark.isChecked()
296288
guiFont = self.guiFont.text()
297289
guiFontSize = self.guiFontSize.value()
298-
fullStatus = self.fullStatus.isChecked()
299290
emphLabels = self.emphLabels.isChecked()
300291

301292
# Check if restart is needed
@@ -309,7 +300,6 @@ def saveValues(self):
309300

310301
# Check if refreshing project tree is needed
311302
refreshTree = False
312-
refreshTree |= self.mainConf.fullStatus != fullStatus
313303
refreshTree |= self.mainConf.emphLabels != emphLabels
314304

315305
self.mainConf.guiLang = guiLang
@@ -318,7 +308,6 @@ def saveValues(self):
318308
self.mainConf.guiDark = guiDark
319309
self.mainConf.guiFont = guiFont
320310
self.mainConf.guiFontSize = guiFontSize
321-
self.mainConf.fullStatus = fullStatus
322311
self.mainConf.emphLabels = emphLabels
323312
self.mainConf.showFullPath = self.showFullPath.isChecked()
324313
self.mainConf.hideVScroll = self.hideVScroll.isChecked()
@@ -758,6 +747,15 @@ def __init__(self, theParent):
758747
theUnit=self.tr("seconds")
759748
)
760749

750+
# Include Notes in Word Count
751+
self.incNotesWCount = QSwitch()
752+
self.incNotesWCount.setChecked(self.mainConf.incNotesWCount)
753+
self.mainForm.addRow(
754+
self.tr("Include project notes in total word count"),
755+
self.incNotesWCount,
756+
self.tr("Affects the word count shown on the status bar.")
757+
)
758+
761759
# Writing Guides
762760
# ==============
763761
self.mainForm.addGroupLabel(self.tr("Writing Guides"))
@@ -826,6 +824,7 @@ def saveValues(self):
826824

827825
# Word Count
828826
self.mainConf.wordCountTimer = self.wordCountTimer.value()
827+
self.mainConf.incNotesWCount = self.incNotesWCount.isChecked()
829828

830829
# Writing Guides
831830
self.mainConf.showTabsNSpaces = self.showTabsNSpaces.isChecked()

novelwriter/dialogs/updates.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
A dialog box for checking for latest updates
55
66
File History:
7-
Created: 2021-08-21 [1.5-alpah0]
7+
Created: 2021-08-21 [1.5a0]
88
99
This file is a part of novelWriter
1010
Copyright 2018–2021, Veronica Berglyd Olsen

novelwriter/gui/doceditor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
Created: 2019-04-22 [0.0.1] BackgroundWordCounter
99
Created: 2019-09-29 [0.2.1] GuiDocEditSearch
1010
Created: 2020-04-25 [0.4.5] GuiDocEditHeader
11-
Rewritten: 2020-06-15 [0.9.0] GuiDocEditSearch
12-
Created: 2020-06-27 [0.10.0] GuiDocEditFooter
11+
Rewritten: 2020-06-15 [0.9] GuiDocEditSearch
12+
Created: 2020-06-27 [0.10] GuiDocEditFooter
1313
Rewritten: 2020-10-07 [1.0b3] BackgroundWordCounter
1414
1515
This file is a part of novelWriter

novelwriter/gui/docviewer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Created: 2019-05-10 [0.0.1] GuiDocViewer
88
Created: 2019-10-31 [0.3.2] GuiDocViewDetails
99
Created: 2020-04-25 [0.4.5] GuiDocViewHeader
10-
Created: 2020-06-09 [0.8.0] GuiDocViewFooter
10+
Created: 2020-06-09 [0.8] GuiDocViewFooter
1111
Created: 2020-09-08 [1.0b1] GuiDocViewHistory
1212
1313
This file is a part of novelWriter

0 commit comments

Comments
 (0)