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:
Veronica Berglyd Olsen
2021-09-10 00:38:45 +02:00
committed by GitHub
parent b9311e84ce
commit 3c8cb34b0a
19 changed files with 246 additions and 134 deletions
+12 -4
View File
@@ -4,7 +4,7 @@ novelWriter Common Functions
Various common functions
File History:
Created: 2019-05-12 [0.1.0]
Created: 2019-05-12 [0.1]
This file is a part of novelWriter
Copyright 20182021, Veronica Berglyd Olsen
@@ -441,9 +441,10 @@ class NWConfigParser(ConfigParser):
CNF_STR = 0
CNF_INT = 1
CNF_BOOL = 2
CNF_S_LST = 3
CNF_I_LST = 4
CNF_FLOAT = 2
CNF_BOOL = 3
CNF_S_LST = 4
CNF_I_LST = 5
def __init__(self):
super().__init__()
@@ -458,6 +459,11 @@ class NWConfigParser(ConfigParser):
"""
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):
"""Read boolean value.
"""
@@ -503,6 +509,8 @@ class NWConfigParser(ConfigParser):
return self.get(section, option)
elif type == self.CNF_INT:
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):
+13 -11
View File
@@ -108,7 +108,6 @@ class Config:
# Features
self.hideVScroll = False # Hide vertical 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
# Project
@@ -145,6 +144,7 @@ class Config:
self.wordCountTimer = 5.0 # Interval for word count update in seconds
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.allowOpenSQuote = False # Allow open-ended single quotes
@@ -179,9 +179,9 @@ class Config:
self.askBeforeBackup = True
# State
self.showRefPanel = True
self.viewComments = True
self.viewSynopsis = True
self.showRefPanel = True # The reference panel for the viewer is visible
self.viewComments = True # Comments are shown in the viewer
self.viewSynopsis = True # Synopsis is shown in the viewer
# Check Qt5 Versions
verQt = splitVersionNumber(QT_VERSION_STR)
@@ -466,7 +466,6 @@ class Config:
cnfSec = "Project"
self.autoSaveProj = theConf.rdInt(cnfSec, "autosaveproject", self.autoSaveProj)
self.autoSaveDoc = theConf.rdInt(cnfSec, "autosavedoc", self.autoSaveDoc)
self.fullStatus = theConf.rdBool(cnfSec, "fullstatus", self.fullStatus)
self.emphLabels = theConf.rdBool(cnfSec, "emphlabels", self.emphLabels)
# Editor
@@ -498,7 +497,9 @@ class Config:
self.showTabsNSpaces = theConf.rdBool(cnfSec, "showtabsnspaces", self.showTabsNSpaces)
self.showLineEndings = theConf.rdBool(cnfSec, "showlineendings", self.showLineEndings)
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.incNotesWCount = theConf.rdBool(cnfSec, "incnoteswcount", self.incNotesWCount)
self.showFullPath = theConf.rdBool(cnfSec, "showfullpath", self.showFullPath)
self.highlightQuotes = theConf.rdBool(cnfSec, "highlightquotes", self.highlightQuotes)
self.allowOpenSQuote = theConf.rdBool(cnfSec, "allowopensquote", self.allowOpenSQuote)
@@ -588,7 +589,6 @@ class Config:
theConf["Project"] = {
"autosaveproject": str(self.autoSaveProj),
"autosavedoc": str(self.autoSaveDoc),
"fullstatus": str(self.fullStatus),
"emphlabels": str(self.emphLabels),
}
@@ -620,7 +620,9 @@ class Config:
"showtabsnspaces": str(self.showTabsNSpaces),
"showlineendings": str(self.showLineEndings),
"showmultispaces": str(self.showMultiSpaces),
"wordcounttimer": str(self.wordCountTimer),
"bigdoclimit": str(self.bigDocLimit),
"incnoteswcount": str(self.incNotesWCount),
"showfullpath": str(self.showFullPath),
"highlightquotes": str(self.highlightQuotes),
"allowopensquote": str(self.allowOpenSQuote),
@@ -821,7 +823,7 @@ class Config:
return True
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
return True
@@ -832,22 +834,22 @@ class Config:
def setOutlinePanePos(self, panePos):
self.outlnPanePos = [int(x/self.guiScale) for x in panePos]
self.confChanged = True
self.confChanged = True
return True
def setShowRefPanel(self, checkState):
self.showRefPanel = checkState
self.confChanged = True
self.confChanged = True
return self.showRefPanel
def setViewComments(self, viewState):
self.viewComments = viewState
self.confChanged = True
self.confChanged = True
return self.viewComments
def setViewSynopsis(self, viewState):
self.viewSynopsis = viewState
self.confChanged = True
self.confChanged = True
return self.viewSynopsis
##
+29 -29
View File
@@ -99,9 +99,11 @@ class NWProject():
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.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.novelWCount = 0 # Total number of words in novel files
self.notesWCount = 0 # Total number of words in note files
self.currNovelWC = 0 # The novel files word count in cutrent session
self.currNotesWC = 0 # The note files word count in cutrent session
self.doBackup = True # Run project backup on exit
# Internal Mapping
@@ -226,9 +228,11 @@ class NWProject():
self.lastEdited = None
self.lastViewed = None
self.lastWCount = 0
self.lastNovelWC = 0
self.lastNotesWC = 0
self.currWCount = 0
self.novelWCount = 0
self.notesWCount = 0
self.currNovelWC = 0
self.currNotesWC = 0
return
@@ -566,9 +570,9 @@ class NWProject():
elif xItem.tag == "lastWordCount":
self.lastWCount = checkInt(xItem.text, 0, False)
elif xItem.tag == "novelWordCount":
self.novelWCount = checkInt(xItem.text, 0, False)
self.lastNovelWC = checkInt(xItem.text, 0, False)
elif xItem.tag == "notesWordCount":
self.notesWCount = checkInt(xItem.text, 0, False)
self.lastNotesWC = checkInt(xItem.text, 0, False)
elif xItem.tag == "status":
self.statusItems.unpackXML(xItem)
elif xItem.tag == "importance":
@@ -610,8 +614,8 @@ class NWProject():
self._scanProjectFolder()
self._loadProjectLocalisation()
self.updateWordCounts()
self.currWCount = self.lastWCount
self.projOpened = time()
self.projAltered = False
@@ -652,11 +656,8 @@ class NWProject():
"timeStamp": formatTimeStamp(saveTime),
})
self.updateWordCounts()
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
xProject = etree.SubElement(nwXML, "project")
@@ -677,8 +678,8 @@ class NWProject():
self._packProjectValue(xSettings, "lastEdited", self.lastEdited)
self._packProjectValue(xSettings, "lastViewed", self.lastViewed)
self._packProjectValue(xSettings, "lastWordCount", self.currWCount)
self._packProjectValue(xSettings, "novelWordCount", wcNovel)
self._packProjectValue(xSettings, "notesWordCount", wcNotes)
self._packProjectValue(xSettings, "novelWordCount", self.currNovelWC)
self._packProjectValue(xSettings, "notesWordCount", self.currNotesWC)
self._packProjectKeyValue(xSettings, "autoReplace", self.autoReplace)
xTitleFmt = etree.SubElement(xSettings, "titleFormat")
@@ -1067,14 +1068,6 @@ class NWProject():
self.setProjectChanged(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):
"""Update the list of novel file status flags. Also iterate
through the project and replace keys that have been renamed.
@@ -1145,11 +1138,6 @@ class NWProject():
return authString
def getSessionWordCount(self):
"""Returns the number of words added or removed this session.
"""
return self.currWCount - self.lastWCount
def getCurrentEditTime(self):
"""Get the total project edit time, including the time spent in
the current session.
@@ -1202,6 +1190,18 @@ class NWProject():
# 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):
"""Count how many times the various status flags are used in the
project tree. The counts themselves are kept in the NWStatus
@@ -1460,7 +1460,7 @@ class NWProject():
isFile = os.path.isfile(sessionFile)
nowTime = time()
sessDiff = self.getSessionWordCount()
sessDiff = self.currWCount - self.lastWCount
sessTime = nowTime - self.projOpened
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" % (
formatTimeStamp(self.projOpened),
formatTimeStamp(nowTime),
self.novelWCount,
self.notesWCount,
self.currNovelWC,
self.currNotesWC,
int(idleTime),
))
+1 -1
View File
@@ -190,7 +190,7 @@ class NWTree():
return True
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
novelWords = 0
+10 -11
View File
@@ -244,14 +244,6 @@ class GuiPreferencesGeneral(QWidget):
# ============
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.setChecked(self.mainConf.emphLabels)
self.mainForm.addRow(
@@ -295,7 +287,6 @@ class GuiPreferencesGeneral(QWidget):
guiDark = self.guiDark.isChecked()
guiFont = self.guiFont.text()
guiFontSize = self.guiFontSize.value()
fullStatus = self.fullStatus.isChecked()
emphLabels = self.emphLabels.isChecked()
# Check if restart is needed
@@ -309,7 +300,6 @@ class GuiPreferencesGeneral(QWidget):
# Check if refreshing project tree is needed
refreshTree = False
refreshTree |= self.mainConf.fullStatus != fullStatus
refreshTree |= self.mainConf.emphLabels != emphLabels
self.mainConf.guiLang = guiLang
@@ -318,7 +308,6 @@ class GuiPreferencesGeneral(QWidget):
self.mainConf.guiDark = guiDark
self.mainConf.guiFont = guiFont
self.mainConf.guiFontSize = guiFontSize
self.mainConf.fullStatus = fullStatus
self.mainConf.emphLabels = emphLabels
self.mainConf.showFullPath = self.showFullPath.isChecked()
self.mainConf.hideVScroll = self.hideVScroll.isChecked()
@@ -758,6 +747,15 @@ class GuiPreferencesEditor(QWidget):
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
# ==============
self.mainForm.addGroupLabel(self.tr("Writing Guides"))
@@ -826,6 +824,7 @@ class GuiPreferencesEditor(QWidget):
# Word Count
self.mainConf.wordCountTimer = self.wordCountTimer.value()
self.mainConf.incNotesWCount = self.incNotesWCount.isChecked()
# Writing Guides
self.mainConf.showTabsNSpaces = self.showTabsNSpaces.isChecked()
+1 -1
View File
@@ -4,7 +4,7 @@ novelWriter GUI Updates
A dialog box for checking for latest updates
File History:
Created: 2021-08-21 [1.5-alpah0]
Created: 2021-08-21 [1.5a0]
This file is a part of novelWriter
Copyright 20182021, Veronica Berglyd Olsen
+2 -2
View File
@@ -8,8 +8,8 @@ Created: 2018-09-29 [0.0.1] GuiDocEditor
Created: 2019-04-22 [0.0.1] BackgroundWordCounter
Created: 2019-09-29 [0.2.1] GuiDocEditSearch
Created: 2020-04-25 [0.4.5] GuiDocEditHeader
Rewritten: 2020-06-15 [0.9.0] GuiDocEditSearch
Created: 2020-06-27 [0.10.0] GuiDocEditFooter
Rewritten: 2020-06-15 [0.9] GuiDocEditSearch
Created: 2020-06-27 [0.10] GuiDocEditFooter
Rewritten: 2020-10-07 [1.0b3] BackgroundWordCounter
This file is a part of novelWriter
+1 -1
View File
@@ -7,7 +7,7 @@ File History:
Created: 2019-05-10 [0.0.1] GuiDocViewer
Created: 2019-10-31 [0.3.2] GuiDocViewDetails
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
This file is a part of novelWriter
+7 -36
View File
@@ -5,7 +5,7 @@ GUI classes for the main window project tree
File History:
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
Copyright 20182021, Veronica Berglyd Olsen
@@ -51,7 +51,7 @@ class GuiProjectTree(QTreeWidget):
novelItemChanged = pyqtSignal()
noteItemChanged = pyqtSignal()
projectWordCountChanged = pyqtSignal(int, int)
wordCountsChanged = pyqtSignal()
def __init__(self, theParent):
QTreeWidget.__init__(self, theParent)
@@ -86,8 +86,7 @@ class GuiProjectTree(QTreeWidget):
self.setIndentation(iPx)
self.setColumnCount(4)
self.setHeaderLabels([
self.tr("Project Tree"), self.tr("Words"), "",
self.tr("Status") if self.mainConf.fullStatus else ""
self.tr("Project Tree"), self.tr("Words"), "", ""
])
treeHeadItem = self.headerItem()
@@ -305,7 +304,7 @@ class GuiProjectTree(QTreeWidget):
nwItem.setWordCount(wC)
nwItem.setParaCount(pC)
self.propagateCount(tHandle, wC)
self.projectWordCount()
self.wordCountsChanged.emit()
return True
@@ -533,7 +532,7 @@ class GuiProjectTree(QTreeWidget):
self.theIndex.deleteHandle(tHandle)
self._deleteTreeItem(tHandle)
self._setTreeChanged(True)
self.projectWordCount()
self.wordCountsChanged.emit()
else:
# 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.setIcon(self.C_EXPORT, expIcon)
trItem.setIcon(self.C_STATUS, statIcon)
if self.mainConf.fullStatus:
trItem.setText(self.C_STATUS, nwItem.itemStatus)
else:
trItem.setToolTip(self.C_STATUS, nwItem.itemStatus)
trItem.setToolTip(self.C_STATUS, nwItem.itemStatus)
if self.mainConf.emphLabels and nwItem.itemLayout == nwItemLayout.DOCUMENT:
if hLevel in ("H1", "H2"):
@@ -674,25 +669,6 @@ class GuiProjectTree(QTreeWidget):
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):
"""Build the entire project tree from scratch. This depends on
the save project item iterator in the project class which will
@@ -702,11 +678,6 @@ class GuiProjectTree(QTreeWidget):
logger.debug("Building the project tree ...")
self.clearTree()
self.setHeaderLabels([
self.tr("Project Tree"), self.tr("Words"), "",
self.tr("Status") if self.mainConf.fullStatus else ""
])
iCount = 0
for nwItem in self.theProject.getProjectItems():
iCount += 1
@@ -819,7 +790,7 @@ class GuiProjectTree(QTreeWidget):
"""Slot for updating the word count of a specific item.
"""
self.propagateCount(tHandle, wCount)
self.projectWordCount()
self.wordCountsChanged.emit()
return
##
+14 -11
View File
@@ -4,7 +4,8 @@ novelWriter GUI Main Window Status Bar
GUI class for the main window status bar
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
Copyright 20182021, Veronica Berglyd Olsen
@@ -28,7 +29,7 @@ import novelwriter
from time import time
from PyQt5.QtCore import QLocale, pyqtSlot
from PyQt5.QtCore import pyqtSlot, QLocale
from PyQt5.QtGui import QColor, QPainter
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
@@ -125,7 +126,7 @@ class GuiMainStatus(QStatusBar):
"""
self.setRefTime(None)
self.setLanguage(None, "")
self.doUpdateProjectStats(0, 0)
self.setProjectStats(0, 0)
self.setProjectStatus(nwState.NONE)
self.setDocumentStatus(nwState.NONE)
self.updateTime()
@@ -176,6 +177,16 @@ class GuiMainStatus(QStatusBar):
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):
"""Update the session clock.
"""
@@ -211,14 +222,6 @@ class GuiMainStatus(QStatusBar):
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)
def doUpdateProjectStatus(self, isChanged):
"""Slot for updating the project status.
+1 -1
View File
@@ -5,7 +5,7 @@ Classes managing and caching themes and icons
File History:
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
Copyright 20182021, Veronica Berglyd Olsen
+24 -3
View File
@@ -124,7 +124,7 @@ class GuiMain(QMainWindow):
self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
self.treeView.projectWordCountChanged.connect(self.statusBar.doUpdateProjectStats)
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
# Minor GUI Elements
self.statusIcons = []
@@ -529,7 +529,7 @@ class GuiMain(QMainWindow):
self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
self.mainMenu.setAutoOutline(self.theProject.autoOutline)
self.statusBar.setRefTime(self.theProject.projOpened)
self.statusBar.doUpdateProjectStats(self.theProject.currWCount, 0)
self._updateStatusWordCount()
# Restore previously open documents, if any
if self.theProject.lastEdited is not None:
@@ -903,13 +903,13 @@ class GuiMain(QMainWindow):
tItem.setParaCount(pC)
self.treeView.propagateCount(tItem.itemHandle, wC)
self.treeView.setTreeItemValues(tItem.itemHandle)
self.treeView.projectWordCount()
tEnd = time()
self.setStatus(
self.tr("Indexing completed in {0} ms").format(f"{(tEnd - tStart)*1000.0:.1f}")
)
self.docEditor.updateTagHighLighting()
self._updateStatusWordCount()
qApp.restoreOverrideCursor()
if not beQuiet:
@@ -980,6 +980,7 @@ class GuiMain(QMainWindow):
self.novelView.initTree()
self.projView.initOutline()
self.projMeta.initDetails()
self._updateStatusWordCount()
return
@@ -1527,6 +1528,26 @@ class GuiMain(QMainWindow):
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()
def _treeSingleClick(self):
"""Single click on a project tree item just updates the details
+3 -2
View File
@@ -1,5 +1,5 @@
[Main]
timestamp = 2021-08-30 21:27:27
timestamp = 2021-09-10 00:23:50
theme = default
syntax = default_light
icons = typicons_light
@@ -26,7 +26,6 @@ fullscreen = False
[Project]
autosaveproject = 60
autosavedoc = 30
fullstatus = True
emphlabels = True
[Editor]
@@ -57,7 +56,9 @@ spellcheck = en
showtabsnspaces = False
showlineendings = False
showmultispaces = True
wordcounttimer = 5.0
bigdoclimit = 800
incnoteswcount = True
showfullpath = True
highlightquotes = True
allowopensquote = False
@@ -1,5 +1,5 @@
[Main]
timestamp = 2021-08-30 21:45:17
timestamp = 2021-09-10 00:23:52
theme = default
syntax = default_light
icons = typicons_light
@@ -26,7 +26,6 @@ fullscreen = False
[Project]
autosaveproject = 40
autosavedoc = 20
fullstatus = True
emphlabels = True
[Editor]
@@ -57,7 +56,9 @@ spellcheck = en
showtabsnspaces = True
showlineendings = True
showmultispaces = True
wordcounttimer = 5.0
bigdoclimit = 500
incnoteswcount = True
showfullpath = False
highlightquotes = False
allowopensquote = False
+9
View File
@@ -482,6 +482,7 @@ def testBaseCommon_NWConfigParser(fncDir):
"boolopt4 = 0\n"
"list1 = a, b, c\n"
"list2 = 17, 18, 19\n"
"float1 = 4.2\n"
))
cfgParser = NWConfigParser()
@@ -516,6 +517,14 @@ def testBaseCommon_NWConfigParser(fncDir):
assert cfgParser.rdInt("nope", "intopt1", 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
assert cfgParser.rdStrList("main", "list1", []) == []
assert cfgParser.rdStrList("main", "list1", ["x"]) == ["a"]
+12 -12
View File
@@ -519,24 +519,24 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir):
# Flag Setters
# ============
assert not tmpConf.setShowRefPanel(False)
assert not tmpConf.showRefPanel
assert tmpConf.setShowRefPanel(True)
assert tmpConf.setShowRefPanel(False) is False
assert tmpConf.showRefPanel is False
assert tmpConf.setShowRefPanel(True) is True
assert not tmpConf.setViewComments(False)
assert not tmpConf.viewComments
assert tmpConf.setViewComments(True)
assert tmpConf.setViewComments(False) is False
assert tmpConf.viewComments is False
assert tmpConf.setViewComments(True) is True
assert not tmpConf.setViewSynopsis(False)
assert not tmpConf.viewSynopsis
assert tmpConf.setViewSynopsis(True)
assert tmpConf.setViewSynopsis(False) is False
assert tmpConf.viewSynopsis is False
assert tmpConf.setViewSynopsis(True) is True
# Check Final File
# ================
assert tmpConf.confChanged
assert tmpConf.saveConfig()
assert not tmpConf.confChanged
assert tmpConf.confChanged is True
assert tmpConf.saveConfig() is True
assert tmpConf.confChanged is False
copyfile(confFile, testFile)
assert cmpFiles(testFile, compFile, [2, 9, 10])
+3 -6
View File
@@ -868,12 +868,9 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
assert theProject.statusItems._theCounts == [1, 1, 1, 2, 0]
assert theProject.importItems._theCounts == [3, 0, 0, 1, 0]
# Check word counts
# Session stats
theProject.currWCount = 200
theProject.lastWCount = 100
assert theProject.getSessionWordCount() == 100
# Session stats
with monkeypatch.context() as mp:
mp.setattr("os.path.isdir", lambda *a, **k: False)
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)
theProject.projOpened = 1600002000
theProject.novelWCount = 200
theProject.notesWCount = 100
theProject.currNovelWC = 200
theProject.currNotesWC = 100
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.project.time", lambda: 1600005600)
+1 -1
View File
@@ -249,7 +249,7 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf")
compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf")
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)
# Clean up
+100
View File
@@ -0,0 +1,100 @@
"""
novelWriter Main Status Bar Class Tester
==========================================
This file is a part of novelWriter
Copyright 20182021, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
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