From 2f9645491cd34940208222905e6df6f52a9af6bf Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 8 Aug 2020 15:51:59 +0200 Subject: [PATCH 1/5] The histogram bar of the writing stats dialog can now be capped --- nw/gui/writingstats.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index 40df85c9..8268a714 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -36,7 +36,7 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QFont, QPixmap from PyQt5.QtWidgets import ( qApp, QDialog, QTreeWidget, QTreeWidgetItem, QDialogButtonBox, QGridLayout, - QLabel, QGroupBox, QMenu, QAction, QFileDialog + QLabel, QGroupBox, QMenu, QAction, QFileDialog, QSpinBox, QHBoxLayout ) from nw.constants import nwConst, nwFiles, nwAlert @@ -207,6 +207,18 @@ class GuiWritingStats(QDialog): self.filterForm.addWidget(self.groupByDay, 4, 1) self.filterForm.setRowStretch(5, 1) + # Settings + self.histMax = QSpinBox(self) + self.histMax.setMinimum(100) + self.histMax.setMaximum(100000) + self.histMax.setSingleStep(100) + self.histMax.valueChanged.connect(self._updateListBox) + + self.optsBox = QHBoxLayout() + self.optsBox.addStretch(1) + self.optsBox.addWidget(QLabel("Word count cap for histogram"), 0) + self.optsBox.addWidget(self.histMax, 0) + # Buttons self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close) self.buttonBox.rejected.connect(self._doClose) @@ -226,9 +238,10 @@ class GuiWritingStats(QDialog): # Assemble self.outerBox = QGridLayout() self.outerBox.addWidget(self.listBox, 0, 0, 1, 2) - self.outerBox.addWidget(self.infoBox, 1, 0) - self.outerBox.addWidget(self.filterBox, 1, 1) - self.outerBox.addWidget(self.buttonBox, 2, 0, 1, 2) + self.outerBox.addLayout(self.optsBox, 1, 0, 1, 2) + self.outerBox.addWidget(self.infoBox, 2, 0) + self.outerBox.addWidget(self.filterBox, 2, 1) + self.outerBox.addWidget(self.buttonBox, 3, 0, 1, 2) self.outerBox.setRowStretch(0, 1) self.setLayout(self.outerBox) @@ -449,6 +462,7 @@ class GuiWritingStats(QDialog): hideZeros = self.hideZeros.isChecked() hideNegative = self.hideNegative.isChecked() groupByDay = self.groupByDay.isChecked() + histMax = self.histMax.value() # Group the data if groupByDay: @@ -509,7 +523,7 @@ class GuiWritingStats(QDialog): sStart = dStart.strftime(nwConst.tStampFmt) self.filterData.append((dStart, sStart, sDiff, dwTotal, wcNovel, wcNotes)) - listMax = max(listMax, dwTotal) + listMax = min(max(listMax, dwTotal), histMax) pcTotal = wcTotal # Populate the list @@ -522,7 +536,7 @@ class GuiWritingStats(QDialog): if nWords > 0 and listMax > 0: theBar = self.barImage.scaled( - int(200*nWords/listMax), + int(200*min(nWords, histMax)/listMax), self.barHeight, Qt.IgnoreAspectRatio, Qt.FastTransformation From cd0f67d9008c87048844446e94a45bbf8cbfb9b5 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 8 Aug 2020 15:57:45 +0200 Subject: [PATCH 2/5] Prevent the enter key from closing the stats dialog --- nw/gui/writingstats.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index 8268a714..76c45a58 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -220,10 +220,15 @@ class GuiWritingStats(QDialog): self.optsBox.addWidget(self.histMax, 0) # Buttons - self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close) + self.buttonBox = QDialogButtonBox() self.buttonBox.rejected.connect(self._doClose) + self.btnClose = self.buttonBox.addButton(QDialogButtonBox.Close) + self.btnClose.setAutoDefault(False) + self.btnSave = self.buttonBox.addButton("Save As", QDialogButtonBox.ActionRole) + self.btnSave.setAutoDefault(False) + self.saveMenu = QMenu(self) self.btnSave.setMenu(self.saveMenu) From ceabf50cf914e152054737e10aefebcdcf4a9b7b Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 8 Aug 2020 16:01:33 +0200 Subject: [PATCH 3/5] The histogram cap setting is now saved to the options file --- nw/core/options.py | 1 + nw/gui/writingstats.py | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/nw/core/options.py b/nw/core/options.py index 3bdf88f3..a91f6f68 100644 --- a/nw/core/options.py +++ b/nw/core/options.py @@ -58,6 +58,7 @@ class OptionState(): "hideZeros", "hideNegative", "groupByDay", + "histMax", }, "GuiDocSplit": { "spLevel", diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index 76c45a58..387c173e 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -212,11 +212,14 @@ class GuiWritingStats(QDialog): self.histMax.setMinimum(100) self.histMax.setMaximum(100000) self.histMax.setSingleStep(100) + self.histMax.setValue( + self.optState.getInt("GuiWritingStats", "histMax", 2000) + ) self.histMax.valueChanged.connect(self._updateListBox) self.optsBox = QHBoxLayout() self.optsBox.addStretch(1) - self.optsBox.addWidget(QLabel("Word count cap for histogram"), 0) + self.optsBox.addWidget(QLabel("Word count cap for the histogram"), 0) self.optsBox.addWidget(self.histMax, 0) # Buttons @@ -280,6 +283,7 @@ class GuiWritingStats(QDialog): hideZeros = self.hideZeros.isChecked() hideNegative = self.hideNegative.isChecked() groupByDay = self.groupByDay.isChecked() + histMax = self.histMax.value() self.optState.setValue("GuiWritingStats", "winWidth", winWidth) self.optState.setValue("GuiWritingStats", "winHeight", winHeight) @@ -293,6 +297,7 @@ class GuiWritingStats(QDialog): self.optState.setValue("GuiWritingStats", "hideZeros", hideZeros) self.optState.setValue("GuiWritingStats", "hideNegative", hideNegative) self.optState.setValue("GuiWritingStats", "groupByDay", groupByDay) + self.optState.setValue("GuiWritingStats", "histMax", histMax) self.optState.saveSettings() self.close() From 5c1abfd22003cfe4bfc894b42882d2c13ac50138 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 8 Aug 2020 16:11:16 +0200 Subject: [PATCH 4/5] Fix the slot for the various update signals --- nw/gui/writingstats.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index 387c173e..6e4a4df8 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -461,8 +461,10 @@ class GuiWritingStats(QDialog): return True - def _updateListBox(self): - """Load/reload the content of the list box. + def _updateListBox(self, dummyVar=None): + """Load/reload the content of the list box. The dummyVar + variable captures the variable sent from the widgets connecting + to it and discards it. """ self.listBox.clear() self.timeFilter = 0.0 From 364aa774549932f7a21c97a06269aceeb54f905c Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 8 Aug 2020 16:19:47 +0200 Subject: [PATCH 5/5] Added some info about the writing statistics tool in the docs --- docs/source/projects.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/source/projects.rst b/docs/source/projects.rst index dbf90b6c..cc3808ec 100644 --- a/docs/source/projects.rst +++ b/docs/source/projects.rst @@ -277,3 +277,20 @@ Settings`. For the backup to be able to run, the :guilabel:`Working Title` must be set in :guilabel:`Project Settings`. This value is used to generate the folder name for the zip files. Without it, the backup will not run at all, but produce a warning message. + +.. _a_proj_stats: + +Writing Statistics +================== + +When you work on your project, a log file records when you opened it, when you closed it, and how +many words you added to your novel and note files during the session. You can view this file in the +``meta`` folder in the directory where you saved your project. The file is named +``sessionStats.log``. + +A small tool to view the content of this file is available in the :guilabel:`Tools` menu under +:guilabel:`Writing Statistics`. You can also launch it by pressing :kbd:`F6`. + +The tool will show a list of all your sessions, and a set of filters to apply to it. You can also +export the filtered data to a JSON file or to a CSV file that can be opened by a spreadsheet +application like for instance Libre Office Calc.