From b5e11f23032557350f52281c7085c10a9ba825dc Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Mon, 11 Jan 2021 19:47:42 +0100
Subject: [PATCH] Added more info to the forst tab of the Project Details
dialog
---
nw/core/project.py | 21 ++++++++++
nw/gui/mainmenu.py | 2 +-
nw/gui/projdetails.py | 82 +++++++++++++++++++++++++++-----------
tests/test_core_project.py | 21 ++++++++++
4 files changed, 102 insertions(+), 24 deletions(-)
diff --git a/nw/core/project.py b/nw/core/project.py
index ac7bf9ef..8cd9b2ec 100644
--- a/nw/core/project.py
+++ b/nw/core/project.py
@@ -1112,11 +1112,32 @@ class NWProject():
# Getters
##
+ def getAuthors(self):
+ """Returns a formatted string of authors.
+ """
+ nAuth = len(self.bookAuthors)
+ authString = ""
+
+ if nAuth == 1:
+ authString = self.bookAuthors[0]
+ elif nAuth > 1:
+ authString = "%s and %s" % (
+ ", ".join(self.bookAuthors[0:-1]), self.bookAuthors[-1]
+ )
+
+ 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.
+ """
+ return round(self.editTime + time() - self.projOpened)
+
def getProjectItems(self):
"""This function ensures that the item tree loaded is sent to
the GUI tree view in such a way that the tree can be built. That
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index 44348af6..77677e21 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -222,7 +222,7 @@ class GuiMainMenu(QMenuBar):
# Project > Project Details
self.aProjectDetails = QAction("Project Details", self)
self.aProjectDetails.setStatusTip("Project details")
- self.aProjectDetails.setShortcut("Ctrl+Shift+E")
+ self.aProjectDetails.setShortcut("Shift+F6")
self.aProjectDetails.triggered.connect(lambda: self.theParent.showProjectDetailsDialog())
self.projMenu.addAction(self.aProjectDetails)
diff --git a/nw/gui/projdetails.py b/nw/gui/projdetails.py
index 98bcb73e..0270476d 100644
--- a/nw/gui/projdetails.py
+++ b/nw/gui/projdetails.py
@@ -33,7 +33,7 @@ from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (
QWidget, QDialogButtonBox, QVBoxLayout, QTreeWidget, QTreeWidgetItem,
- QLabel, QSpinBox, QGroupBox, QGridLayout, QHBoxLayout
+ QLabel, QSpinBox, QGridLayout, QHBoxLayout, QLineEdit
)
from nw.gui.custom import PagedDialog, QSwitch
@@ -148,6 +148,7 @@ class GuiProjectDetailsMain(QWidget):
bookFont.setWeight(QFont.Bold)
self.bookTitle.setFont(bookFont)
self.bookTitle.setAlignment(Qt.AlignHCenter)
+ self.bookTitle.setWordWrap(True)
self.projName = QLabel("Working Title: %s" % self.theProject.projName)
workFont = self.projName.font()
@@ -155,12 +156,14 @@ class GuiProjectDetailsMain(QWidget):
workFont.setItalic(True)
self.projName.setFont(workFont)
self.projName.setAlignment(Qt.AlignHCenter)
+ self.projName.setWordWrap(True)
- self.bookAuthors = QLabel("By: %s" % ", ".join(self.theProject.bookAuthors))
+ self.bookAuthors = QLabel("By %s" % self.theProject.getAuthors())
authFont = self.bookAuthors.font()
authFont.setPixelSize(round(1.2*fPx))
self.bookAuthors.setFont(authFont)
self.bookAuthors.setAlignment(Qt.AlignHCenter)
+ self.bookAuthors.setWordWrap(True)
# Stats
# =====
@@ -176,20 +179,39 @@ class GuiProjectDetailsMain(QWidget):
self.sceneCountLbl = QLabel("Scenes:")
self.sceneCountVal = QLabel(f"{hCounts[3]:n}")
+ self.revCountLbl = QLabel("Revisions:")
+ self.revCountVal = QLabel(f"{self.theProject.saveCount:n}")
+
+ edTime = self.theProject.getCurrentEditTime()
+ self.editTimeLbl = QLabel("Editing Time:")
+ self.editTimeVal = QLabel(f"{edTime//3600:02d}:{edTime%3600//60:02d}")
+
self.statsGrid = QGridLayout()
- self.statsGrid.addWidget(self.wordCountLbl, 0, 0, 1, 1, Qt.AlignLeft)
- self.statsGrid.addWidget(self.wordCountVal, 0, 1, 1, 1, Qt.AlignRight)
- self.statsGrid.addWidget(self.chapCountLbl, 1, 0, 1, 1, Qt.AlignLeft)
- self.statsGrid.addWidget(self.chapCountVal, 1, 1, 1, 1, Qt.AlignRight)
- self.statsGrid.addWidget(self.sceneCountLbl, 2, 0, 1, 1, Qt.AlignLeft)
- self.statsGrid.addWidget(self.sceneCountVal, 2, 1, 1, 1, Qt.AlignRight)
+ self.statsGrid.addWidget(self.wordCountLbl, 0, 0, 1, 1, Qt.AlignRight)
+ self.statsGrid.addWidget(self.wordCountVal, 0, 1, 1, 1, Qt.AlignLeft)
+ self.statsGrid.addWidget(self.chapCountLbl, 1, 0, 1, 1, Qt.AlignRight)
+ self.statsGrid.addWidget(self.chapCountVal, 1, 1, 1, 1, Qt.AlignLeft)
+ self.statsGrid.addWidget(self.sceneCountLbl, 2, 0, 1, 1, Qt.AlignRight)
+ self.statsGrid.addWidget(self.sceneCountVal, 2, 1, 1, 1, Qt.AlignLeft)
+ self.statsGrid.addWidget(self.revCountLbl, 3, 0, 1, 1, Qt.AlignRight)
+ self.statsGrid.addWidget(self.revCountVal, 3, 1, 1, 1, Qt.AlignLeft)
+ self.statsGrid.addWidget(self.editTimeLbl, 4, 0, 1, 1, Qt.AlignRight)
+ self.statsGrid.addWidget(self.editTimeVal, 4, 1, 1, 1, Qt.AlignLeft)
self.statsGrid.setHorizontalSpacing(hPx)
self.statsGrid.setVerticalSpacing(vPx)
- self.statsBox = QHBoxLayout()
- self.statsBox.addStretch(1)
- self.statsBox.addLayout(self.statsGrid)
- self.statsBox.addStretch(1)
+ # Meta
+ # ====
+
+ self.projPathLbl = QLabel("Path:")
+ self.projPathVal = QLineEdit()
+ self.projPathVal.setText(self.theProject.projPath)
+ self.projPathVal.setReadOnly(True)
+
+ self.projPathBox = QHBoxLayout()
+ self.projPathBox.addWidget(self.projPathLbl)
+ self.projPathBox.addWidget(self.projPathVal)
+ self.projPathBox.setSpacing(hPx)
# Assemble
# ========
@@ -199,8 +221,10 @@ class GuiProjectDetailsMain(QWidget):
self.outerBox.addWidget(self.projName)
self.outerBox.addWidget(self.bookAuthors)
self.outerBox.addSpacing(round(2.5*fPx))
- self.outerBox.addLayout(self.statsBox)
+ self.outerBox.addLayout(self.statsGrid)
+ self.outerBox.addSpacing(round(0.8*fPx))
self.outerBox.addStretch(1)
+ self.outerBox.addLayout(self.projPathBox)
self.setLayout(self.outerBox)
@@ -230,6 +254,7 @@ class GuiProjectDetailsContents(QWidget):
self._theToC = []
iPx = self.theTheme.baseIconSize
+ hPx = self.mainConf.pxInt(12)
# Contents Tree
# =============
@@ -265,38 +290,49 @@ class GuiProjectDetailsContents(QWidget):
# Options
# =======
- wordsPerPage = self.optState.getInt("GuiProjectDetails", "wordsPerPage", 300)
+ wordsPerPage = self.optState.getInt("GuiProjectDetails", "wordsPerPage", 350)
clearDouble = self.optState.getInt("GuiProjectDetails", "clearDouble", True)
- self.optionsBox = QGroupBox("Options", self)
- self.optionsForm = QGridLayout(self)
- self.optionsBox.setLayout(self.optionsForm)
+ wordsHelp = (
+ "Typical word count for a 5\u00d78 inch book page with 11 pt font is 350."
+ )
+ dblHelp = (
+ "Assume a new chapter or partition always start on an odd numbered page."
+ )
self.wpLabel = QLabel("Words per page")
+ self.wpLabel.setToolTip(wordsHelp)
+
self.wpValue = QSpinBox()
self.wpValue.setMinimum(10)
self.wpValue.setMaximum(1000)
self.wpValue.setSingleStep(10)
self.wpValue.setValue(wordsPerPage)
+ self.wpValue.setToolTip(wordsHelp)
self.wpValue.valueChanged.connect(self._populateTree)
self.dblLabel = QLabel("Clear double pages")
+ self.dblLabel.setToolTip(dblHelp)
+
self.dblValue = QSwitch(self, 2*iPx, iPx)
self.dblValue.setChecked(clearDouble)
+ self.dblValue.setToolTip(dblHelp)
self.dblValue.clicked.connect(self._populateTree)
- self.optionsForm.addWidget(self.wpLabel, 0, 0, 1, 1, Qt.AlignLeft)
- self.optionsForm.addWidget(self.wpValue, 0, 1, 1, 1, Qt.AlignRight)
- self.optionsForm.addWidget(self.dblLabel, 1, 0, 1, 1, Qt.AlignLeft)
- self.optionsForm.addWidget(self.dblValue, 1, 1, 1, 1, Qt.AlignRight)
- self.optionsForm.setColumnStretch(2, 1)
+ self.optionsBox = QHBoxLayout()
+ self.optionsBox.addWidget(self.wpLabel)
+ self.optionsBox.addWidget(self.wpValue)
+ self.optionsBox.addStretch(1)
+ self.optionsBox.addWidget(self.dblLabel)
+ self.optionsBox.addWidget(self.dblValue)
+ self.optionsBox.setSpacing(hPx)
# Assemble
# ========
self.outerBox = QVBoxLayout()
self.outerBox.addWidget(self.chTree)
- self.outerBox.addWidget(self.optionsBox)
+ self.outerBox.addLayout(self.optionsBox)
self.setLayout(self.outerBox)
diff --git a/tests/test_core_project.py b/tests/test_core_project.py
index 57ee8f51..6fbe14c9 100644
--- a/tests/test_core_project.py
+++ b/tests/test_core_project.py
@@ -682,10 +682,31 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, dummyGUI, tmpDir):
assert theProject.bookTitle == "A Title"
# Project Authors
+ # Check that the list is cleaned up and that it can be extracted as
+ # a properly formatted string, depending on number of names
assert not theProject.setBookAuthors([])
assert theProject.setBookAuthors(" Jane Doe \n John Doh \n ")
assert theProject.bookAuthors == ["Jane Doe", "John Doh"]
+ assert theProject.setBookAuthors("")
+ assert theProject.getAuthors() == ""
+
+ assert theProject.setBookAuthors("Jane Doe")
+ assert theProject.getAuthors() == "Jane Doe"
+
+ assert theProject.setBookAuthors("Jane Doe\nJohn Doh")
+ assert theProject.getAuthors() == "Jane Doe and John Doh"
+
+ assert theProject.setBookAuthors("Jane Doe\nJohn Doh\nBod Owens")
+ assert theProject.getAuthors() == "Jane Doe, John Doh and Bod Owens"
+
+ # Edit Time
+ theProject.editTime = 1234
+ theProject.projOpened = 1600000000
+ monkeypatch.setattr("nw.core.project.time", lambda: 1600005600)
+ assert theProject.getCurrentEditTime() == 6834
+ monkeypatch.undo()
+
# Trash folder
# Should create on first call, and just returned on later calls
assert theProject.projTree["73475cb40a568"] is None