GUI and code tweaks and fixes (#852)

* Improve format menu header descriptions
* Ensure that item status is parsed after item class from XML
* Fix column alignment in ToC.txt file
* Rename test variable and fix outdated docstring
* Fix ToC.txt underline
* Rename the Layout label on the item details panel
* Add option to emphasise H1 and H2 labels in the project tree
* Rename the main column of the novel tree to match project tree
* Use the same document icons in the outline as the project tree
* Move project tree settings to Project section of config file
This commit is contained in:
Veronica Berglyd Olsen
2021-08-17 21:45:18 +02:00
committed by GitHub
parent f7c768bb91
commit a9368904e5
16 changed files with 120 additions and 81 deletions
+5 -2
View File
@@ -111,6 +111,7 @@ class Config:
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
self.autoSaveProj = 60 # Interval for auto-saving project in seconds
@@ -451,7 +452,6 @@ class Config:
self.guiLang = theConf.rdStr(cnfSec, "guilang", self.guiLang)
self.hideVScroll = theConf.rdBool(cnfSec, "hidevscroll", self.hideVScroll)
self.hideHScroll = theConf.rdBool(cnfSec, "hidehscroll", self.hideHScroll)
self.fullStatus = theConf.rdBool(cnfSec, "fullstatus", self.fullStatus)
# Sizes
cnfSec = "Sizes"
@@ -470,6 +470,8 @@ 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
cnfSec = "Editor"
@@ -567,7 +569,6 @@ class Config:
"guilang": str(self.guiLang),
"hidevscroll": str(self.hideVScroll),
"hidehscroll": str(self.hideHScroll),
"fullstatus": str(self.fullStatus),
}
theConf["Sizes"] = {
@@ -586,6 +587,8 @@ class Config:
theConf["Project"] = {
"autosaveproject": str(self.autoSaveProj),
"autosavedoc": str(self.autoSaveDoc),
"fullstatus": str(self.fullStatus),
"emphlabels": str(self.emphLabels),
}
theConf["Editor"] = {
+5 -1
View File
@@ -107,6 +107,7 @@ class NWItem():
if "order" in xItem.attrib:
self.setOrder(xItem.attrib["order"])
tmpStatus = ""
for xValue in xItem:
if xValue.tag == "name":
self.setName(xValue.text)
@@ -117,7 +118,7 @@ class NWItem():
elif xValue.tag == "layout":
self.setLayout(xValue.text)
elif xValue.tag == "status":
self.setStatus(xValue.text)
tmpStatus = xValue.text
elif xValue.tag == "expanded":
self.setExpanded(xValue.text)
elif xValue.tag == "exported":
@@ -136,6 +137,9 @@ class NWItem():
# version of novelWriter that doesn't know the tag.
logger.error("Unknown tag '%s'", xValue.tag)
# Guarantees that <status> is parsed after <class>
self.setStatus(tmpStatus)
return True
@staticmethod
+3 -3
View File
@@ -158,7 +158,7 @@ class NWTree():
continue
tFile = tHandle+".nwd"
if os.path.isfile(os.path.join(self.theProject.projContent, tFile)):
tocLine = "%-25s %-9s %-10s %s" % (
tocLine = "%-25s %-9s %-8s %s" % (
os.path.join("content", tFile),
tItem.itemClass.name,
tItem.itemLayout.name,
@@ -175,10 +175,10 @@ class NWTree():
outFile.write("Table of Contents\n")
outFile.write("=================\n")
outFile.write("\n")
outFile.write("%-25s %-9s %-10s %s\n" % (
outFile.write("%-25s %-9s %-8s %s\n" % (
"File Name", "Class", "Layout", "Document Label"
))
outFile.write("-"*tocLen + "\n")
outFile.write("-"*max(tocLen, 62) + "\n")
outFile.write("\n".join(tocList))
outFile.write("\n")
+21 -4
View File
@@ -94,7 +94,7 @@ class GuiPreferences(PagedDialog):
"""
logger.debug("Saving new preferences")
needsRestart = self.tabGeneral.saveValues()
needsRestart, refreshTree = self.tabGeneral.saveValues()
self.tabProjects.saveValues()
self.tabDocs.saveValues()
@@ -108,6 +108,9 @@ class GuiPreferences(PagedDialog):
"Some changes will not be applied until novelWriter has been restarted."
), nwAlert.INFO)
if refreshTree:
self.theParent.treeView.buildTree()
self._saveWindowSize()
self.accept()
@@ -248,7 +251,15 @@ class GuiPreferencesGeneral(QWidget):
self.mainForm.addRow(
self.tr("Show status text in project tree"),
self.fullStatus,
self.tr("Changing this requires restarting novelWriter."),
self.tr("If disabled, only the icon is shown."),
)
self.emphLabels = QSwitch()
self.emphLabels.setChecked(self.mainConf.emphLabels)
self.mainForm.addRow(
self.tr("Emphasise partition and chapter labels"),
self.emphLabels,
self.tr("The novel document labels will be bold and underlined."),
)
self.showFullPath = QSwitch()
@@ -287,6 +298,7 @@ class GuiPreferencesGeneral(QWidget):
guiFont = self.guiFont.text()
guiFontSize = self.guiFontSize.value()
fullStatus = self.fullStatus.isChecked()
emphLabels = self.emphLabels.isChecked()
# Check if restart is needed
needsRestart = False
@@ -296,7 +308,11 @@ class GuiPreferencesGeneral(QWidget):
needsRestart |= self.mainConf.guiDark != guiDark
needsRestart |= self.mainConf.guiFont != guiFont
needsRestart |= self.mainConf.guiFontSize != guiFontSize
needsRestart |= self.mainConf.fullStatus != fullStatus
# Check if refreshing project tree is needed
refreshTree = False
refreshTree |= self.mainConf.fullStatus != fullStatus
refreshTree |= self.mainConf.emphLabels != emphLabels
self.mainConf.guiLang = guiLang
self.mainConf.guiTheme = guiTheme
@@ -305,13 +321,14 @@ class GuiPreferencesGeneral(QWidget):
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()
self.mainConf.hideHScroll = self.hideHScroll.isChecked()
self.mainConf.confChanged = True
return needsRestart
return needsRestart, refreshTree
##
# Slots
+1 -1
View File
@@ -178,7 +178,7 @@ def exceptionHandler(exType, exValue, exTrace):
errMsg.exec_()
try:
# Try a controlled shudown
# Try a controlled shutdown
nwGUI.closeProject(isYes=True)
nwGUI.closeMain()
logger.info("Emergency shutdown successful")
+33 -33
View File
@@ -72,8 +72,8 @@ class GuiItemDetails(QWidget):
self.labelName.setFont(fntLabel)
self.labelName.setAlignment(Qt.AlignLeft | Qt.AlignBaseline)
self.labelFlag = QLabel("")
self.labelFlag.setAlignment(Qt.AlignRight | Qt.AlignBaseline)
self.labelIcon = QLabel("")
self.labelIcon.setAlignment(Qt.AlignRight | Qt.AlignBaseline)
self.labelData = QLabel("")
self.labelData.setFont(fntValue)
@@ -85,8 +85,8 @@ class GuiItemDetails(QWidget):
self.statusName.setFont(fntLabel)
self.statusName.setAlignment(Qt.AlignLeft)
self.statusFlag = QLabel("")
self.statusFlag.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.statusIcon = QLabel("")
self.statusIcon.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.statusData = QLabel("")
self.statusData.setFont(fntValue)
@@ -97,24 +97,24 @@ class GuiItemDetails(QWidget):
self.className.setFont(fntLabel)
self.className.setAlignment(Qt.AlignLeft)
self.classFlag = QLabel("")
self.classFlag.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.classIcon = QLabel("")
self.classIcon.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.classData = QLabel("")
self.classData.setFont(fntValue)
self.classData.setAlignment(Qt.AlignLeft)
# Layout
self.layoutName = QLabel(self.tr("Layout"))
self.layoutName.setFont(fntLabel)
self.layoutName.setAlignment(Qt.AlignLeft)
self.usageName = QLabel(self.tr("Usage"))
self.usageName.setFont(fntLabel)
self.usageName.setAlignment(Qt.AlignLeft)
self.layoutFlag = QLabel("")
self.layoutFlag.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.usageIcon = QLabel("")
self.usageIcon.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.layoutData = QLabel("")
self.layoutData.setFont(fntValue)
self.layoutData.setAlignment(Qt.AlignLeft)
self.usageData = QLabel("")
self.usageData.setFont(fntValue)
self.usageData.setAlignment(Qt.AlignLeft)
# Character Count
self.cCountName = QLabel(" "+self.tr("Characters"))
@@ -146,24 +146,24 @@ class GuiItemDetails(QWidget):
# Assemble
self.mainBox = QGridLayout(self)
self.mainBox.addWidget(self.labelName, 0, 0, 1, 1)
self.mainBox.addWidget(self.labelFlag, 0, 1, 1, 1)
self.mainBox.addWidget(self.labelIcon, 0, 1, 1, 1)
self.mainBox.addWidget(self.labelData, 0, 2, 1, 3)
self.mainBox.addWidget(self.statusName, 1, 0, 1, 1)
self.mainBox.addWidget(self.statusFlag, 1, 1, 1, 1)
self.mainBox.addWidget(self.statusIcon, 1, 1, 1, 1)
self.mainBox.addWidget(self.statusData, 1, 2, 1, 1)
self.mainBox.addWidget(self.cCountName, 1, 3, 1, 1)
self.mainBox.addWidget(self.cCountData, 1, 4, 1, 1)
self.mainBox.addWidget(self.className, 2, 0, 1, 1)
self.mainBox.addWidget(self.classFlag, 2, 1, 1, 1)
self.mainBox.addWidget(self.classIcon, 2, 1, 1, 1)
self.mainBox.addWidget(self.classData, 2, 2, 1, 1)
self.mainBox.addWidget(self.wCountName, 2, 3, 1, 1)
self.mainBox.addWidget(self.wCountData, 2, 4, 1, 1)
self.mainBox.addWidget(self.layoutName, 3, 0, 1, 1)
self.mainBox.addWidget(self.layoutFlag, 3, 1, 1, 1)
self.mainBox.addWidget(self.layoutData, 3, 2, 1, 1)
self.mainBox.addWidget(self.usageName, 3, 0, 1, 1)
self.mainBox.addWidget(self.usageIcon, 3, 1, 1, 1)
self.mainBox.addWidget(self.usageData, 3, 2, 1, 1)
self.mainBox.addWidget(self.pCountName, 3, 3, 1, 1)
self.mainBox.addWidget(self.pCountData, 3, 4, 1, 1)
@@ -198,15 +198,15 @@ class GuiItemDetails(QWidget):
"""
self._itemHandle = None
self.labelFlag.setPixmap(QPixmap(1, 1))
self.statusFlag.setPixmap(QPixmap(1, 1))
self.classFlag.setText("")
self.layoutFlag.setText("")
self.labelIcon.setPixmap(QPixmap(1, 1))
self.statusIcon.setPixmap(QPixmap(1, 1))
self.classIcon.setText("")
self.usageIcon.setText("")
self.labelData.setText("")
self.statusData.setText("")
self.classData.setText("")
self.layoutData.setText("")
self.usageData.setText("")
self.cCountData.setText("")
self.wCountData.setText("")
@@ -238,11 +238,11 @@ class GuiItemDetails(QWidget):
if nwItem.itemType == nwItemType.FILE:
if nwItem.isExported:
self.labelFlag.setPixmap(self._expCheck)
self.labelIcon.setPixmap(self._expCheck)
else:
self.labelFlag.setPixmap(self._expCross)
self.labelIcon.setPixmap(self._expCross)
else:
self.labelFlag.setPixmap(QPixmap(1, 1))
self.labelIcon.setPixmap(QPixmap(1, 1))
self.labelData.setText(theLabel)
@@ -257,25 +257,25 @@ class GuiItemDetails(QWidget):
itStatus = self.theProject.importItems.checkEntry(itStatus) # Make sure it's valid
flagIcon = self.theParent.importIcons[itStatus]
self.statusFlag.setPixmap(flagIcon.pixmap(iPx, iPx))
self.statusIcon.setPixmap(flagIcon.pixmap(iPx, iPx))
self.statusData.setText(nwItem.itemStatus)
# Class
# =====
classIcon = self.theTheme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass])
self.classFlag.setPixmap(classIcon.pixmap(iPx, iPx))
self.classIcon.setPixmap(classIcon.pixmap(iPx, iPx))
self.classData.setText(trConst(nwLabels.CLASS_NAME[nwItem.itemClass]))
# Layout
# ======
hLevel = self.theParent.theIndex.getHandleHeaderLevel(tHandle)
layoutIcon = self.theTheme.getItemIcon(
usageIcon = self.theTheme.getItemIcon(
nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel
)
self.layoutFlag.setPixmap(layoutIcon.pixmap(iPx, iPx))
self.layoutData.setText(nwItem.describeMe(hLevel))
self.usageIcon.setPixmap(usageIcon.pixmap(iPx, iPx))
self.usageData.setText(nwItem.describeMe(hLevel))
# Counts
# ======
+8 -8
View File
@@ -818,29 +818,29 @@ class GuiMainMenu(QMenuBar):
# Format > Separator
self.fmtMenu.addSeparator()
# Format > Header 1
self.aFmtHead1 = QAction(self.tr("Header 1"), self)
# Format > Header 1 (Partition)
self.aFmtHead1 = QAction(self.tr("Header 1 (Partition)"), self)
self.aFmtHead1.setStatusTip(self.tr("Change the block format to Header 1"))
self.aFmtHead1.setShortcut("Ctrl+1")
self.aFmtHead1.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H1))
self.fmtMenu.addAction(self.aFmtHead1)
# Format > Header 2
self.aFmtHead2 = QAction(self.tr("Header 2"), self)
# Format > Header 2 (Chapter)
self.aFmtHead2 = QAction(self.tr("Header 2 (Chapter)"), self)
self.aFmtHead2.setStatusTip(self.tr("Change the block format to Header 2"))
self.aFmtHead2.setShortcut("Ctrl+2")
self.aFmtHead2.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H2))
self.fmtMenu.addAction(self.aFmtHead2)
# Format > Header 3
self.aFmtHead3 = QAction(self.tr("Header 3"), self)
# Format > Header 3 (Scene)
self.aFmtHead3 = QAction(self.tr("Header 3 (Scene)"), self)
self.aFmtHead3.setStatusTip(self.tr("Change the block format to Header 3"))
self.aFmtHead3.setShortcut("Ctrl+3")
self.aFmtHead3.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H3))
self.fmtMenu.addAction(self.aFmtHead3)
# Format > Header 4
self.aFmtHead4 = QAction(self.tr("Header 4"), self)
# Format > Header 4 (Section)
self.aFmtHead4 = QAction(self.tr("Header 4 (Section)"), self)
self.aFmtHead4.setStatusTip(self.tr("Change the block format to Header 4"))
self.aFmtHead4.setShortcut("Ctrl+4")
self.aFmtHead4.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H4))
+1 -1
View File
@@ -64,7 +64,7 @@ class GuiNovelTree(QTreeWidget):
self.setIndentation(iPx)
self.setColumnCount(3)
self.setHeaderLabels([
self.tr("Title"),
self.tr("Novel Outline"),
self.tr("Words"),
self.tr("POV")
])
+5 -2
View File
@@ -33,7 +33,7 @@ from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QMenu, QAction, QAbstractItemView
)
from nw.enum import nwOutline
from nw.enum import nwItemLayout, nwItemType, nwOutline
from nw.constants import trConst, nwKeyWords, nwLabels
logger = logging.getLogger(__name__)
@@ -434,6 +434,9 @@ class GuiOutline(QTreeWidget):
newItem = QTreeWidgetItem()
hIcon = "doc_%s" % novIdx["level"].lower()
hLevel = self.theIndex.getHandleHeaderLevel(tHandle)
dIcon = self.theTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, hLevel)
cC = int(novIdx["cCount"])
wC = int(novIdx["wCount"])
pC = int(novIdx["pCount"])
@@ -443,7 +446,7 @@ class GuiOutline(QTreeWidget):
newItem.setIcon(self._colIdx[nwOutline.TITLE], self.theTheme.getIcon(hIcon))
newItem.setText(self._colIdx[nwOutline.LEVEL], novIdx["level"])
newItem.setText(self._colIdx[nwOutline.LABEL], nwItem.itemName)
newItem.setIcon(self._colIdx[nwOutline.LABEL], self.theTheme.getIcon("proj_document"))
newItem.setIcon(self._colIdx[nwOutline.LABEL], dIcon)
newItem.setText(self._colIdx[nwOutline.LINE], sTitle[1:].lstrip("0"))
newItem.setData(self._colIdx[nwOutline.LINE], Qt.UserRole, sTitle)
newItem.setText(self._colIdx[nwOutline.SYNOP], novIdx["synopsis"])
+13 -1
View File
@@ -86,7 +86,7 @@ class GuiProjectTree(QTreeWidget):
self.setIndentation(iPx)
self.setColumnCount(4)
self.setHeaderLabels([
self.tr("Label"), self.tr("Words"), "",
self.tr("Project Tree"), self.tr("Words"), "",
self.tr("Status") if self.mainConf.fullStatus else ""
])
@@ -636,6 +636,13 @@ class GuiProjectTree(QTreeWidget):
else:
trItem.setToolTip(self.C_STATUS, nwItem.itemStatus)
if self.mainConf.emphLabels and nwItem.itemLayout == nwItemLayout.DOCUMENT:
if hLevel in ("H1", "H2"):
trFont = trItem.font(self.C_NAME)
trFont.setBold(True)
trFont.setUnderline(True)
trItem.setFont(self.C_NAME, trFont)
return
def propagateCount(self, tHandle, theCount, nDepth=0):
@@ -695,6 +702,11 @@ 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
+1 -3
View File
@@ -502,9 +502,7 @@ class GuiWritingStats(QDialog):
##
def _updateListBox(self):
"""Load/reload the content of the list box. The dummyVar
variable captures the variable sent from the widgets connecting
to it and discards it.
"""Load/reload the content of the list box.
"""
self.listBox.clear()
self.timeFilter = 0.0