Update Project Details for multi-novel projects (#1130)
This commit is contained in:
@@ -498,13 +498,15 @@ class NWIndex:
|
|||||||
"""
|
"""
|
||||||
return self._itemIndex.mainItemHeader(tHandle)
|
return self._itemIndex.mainItemHeader(tHandle)
|
||||||
|
|
||||||
def getTableOfContents(self, maxDepth, skipExcl=True):
|
def getTableOfContents(self, rootHandle, maxDepth, skipExcl=True):
|
||||||
"""Generate a table of contents up to a maximum depth.
|
"""Generate a table of contents up to a maximum depth.
|
||||||
"""
|
"""
|
||||||
tOrder = []
|
tOrder = []
|
||||||
tData = {}
|
tData = {}
|
||||||
pKey = None
|
pKey = None
|
||||||
for tHandle, sTitle, hItem in self._itemIndex.iterNovelStructure(skipExcl=skipExcl):
|
for tHandle, sTitle, hItem in self._itemIndex.iterNovelStructure(
|
||||||
|
rootHandle=rootHandle, skipExcl=skipExcl
|
||||||
|
):
|
||||||
tKey = f"{tHandle}:{sTitle}"
|
tKey = f"{tHandle}:{sTitle}"
|
||||||
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0)
|
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0)
|
||||||
if iLevel > maxDepth:
|
if iLevel > maxDepth:
|
||||||
|
|||||||
@@ -27,15 +27,17 @@ import math
|
|||||||
import logging
|
import logging
|
||||||
import novelwriter
|
import novelwriter
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt, QSize, pyqtSlot
|
||||||
from PyQt5.QtGui import QFont
|
from PyQt5.QtGui import QFont
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QWidget, QDialogButtonBox, QVBoxLayout, QTreeWidget, QTreeWidgetItem,
|
QAbstractItemView, QComboBox, QDialogButtonBox, QGridLayout, QHBoxLayout,
|
||||||
QLabel, QSpinBox, QGridLayout, QHBoxLayout, QLineEdit, QAbstractItemView
|
QLabel, QLineEdit, QSpinBox, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
||||||
|
QWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from novelwriter.enum import nwItemClass
|
||||||
from novelwriter.common import numberToRoman
|
from novelwriter.common import numberToRoman
|
||||||
from novelwriter.constants import nwUnicode
|
from novelwriter.constants import nwLabels, nwUnicode
|
||||||
from novelwriter.gui.custom import PagedDialog, QSwitch
|
from novelwriter.gui.custom import PagedDialog, QSwitch
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -281,12 +283,26 @@ class GuiProjectDetailsContents(QWidget):
|
|||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
self._theToC = []
|
self._theToC = []
|
||||||
|
self._currentRoot = None
|
||||||
|
|
||||||
iPx = self.mainTheme.baseIconSize
|
iPx = self.mainTheme.baseIconSize
|
||||||
hPx = self.mainConf.pxInt(12)
|
hPx = self.mainConf.pxInt(12)
|
||||||
vPx = self.mainConf.pxInt(4)
|
vPx = self.mainConf.pxInt(4)
|
||||||
pOptions = self.theProject.options
|
pOptions = self.theProject.options
|
||||||
|
|
||||||
|
# Header
|
||||||
|
# ======
|
||||||
|
|
||||||
|
self.tocLabel = QLabel("<b>%s</b>" % self.tr("Table of Contents"))
|
||||||
|
|
||||||
|
self.novelValue = QComboBox(self)
|
||||||
|
self.novelValue.setMinimumWidth(self.mainConf.pxInt(200))
|
||||||
|
self.novelValue.currentIndexChanged.connect(self._novelValueChanged)
|
||||||
|
|
||||||
|
self.headBox = QHBoxLayout()
|
||||||
|
self.headBox.addWidget(self.tocLabel)
|
||||||
|
self.headBox.addWidget(self.novelValue)
|
||||||
|
|
||||||
# Contents Tree
|
# Contents Tree
|
||||||
# =============
|
# =============
|
||||||
|
|
||||||
@@ -389,7 +405,7 @@ class GuiProjectDetailsContents(QWidget):
|
|||||||
# ========
|
# ========
|
||||||
|
|
||||||
self.outerBox = QVBoxLayout()
|
self.outerBox = QVBoxLayout()
|
||||||
self.outerBox.addWidget(QLabel("<b>%s</b>" % self.tr("Table of Contents")))
|
self.outerBox.addLayout(self.headBox)
|
||||||
self.outerBox.addWidget(self.tocTree)
|
self.outerBox.addWidget(self.tocTree)
|
||||||
self.outerBox.addLayout(self.optionsBox)
|
self.outerBox.addLayout(self.optionsBox)
|
||||||
|
|
||||||
@@ -412,19 +428,37 @@ class GuiProjectDetailsContents(QWidget):
|
|||||||
def updateValues(self):
|
def updateValues(self):
|
||||||
"""Populate the tree.
|
"""Populate the tree.
|
||||||
"""
|
"""
|
||||||
self._prepareData()
|
self._currentRoot = None
|
||||||
|
self._populateNovelList()
|
||||||
|
|
||||||
|
rootHandle = self.novelValue.currentData()
|
||||||
|
self._prepareData(rootHandle)
|
||||||
self._populateTree()
|
self._populateTree()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _prepareData(self):
|
def _populateNovelList(self):
|
||||||
"""Extract the data for the tree.
|
"""Fill the novel combo box with a list of all novel folders.
|
||||||
"""
|
"""
|
||||||
self._theToC = []
|
self.novelValue.clear()
|
||||||
self._theToC = self.theProject.index.getTableOfContents(2)
|
|
||||||
|
tIcon = self.mainTheme.getIcon(nwLabels.CLASS_ICON[nwItemClass.NOVEL])
|
||||||
|
for tHandle, nwItem in self.theProject.tree.iterRoots(nwItemClass.NOVEL):
|
||||||
|
self.novelValue.addItem(tIcon, nwItem.itemName, tHandle)
|
||||||
|
|
||||||
|
self.novelValue.setVisible(self.novelValue.count() > 1)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def _prepareData(self, rootHandle):
|
||||||
|
"""Extract the information from the project index.
|
||||||
|
"""
|
||||||
|
logger.debug("Populating ToC from handle '%s'", rootHandle)
|
||||||
|
self._theToC = self.theProject.index.getTableOfContents(rootHandle, 2)
|
||||||
self._theToC.append(("", 0, self.tr("END"), 0))
|
self._theToC.append(("", 0, self.tr("END"), 0))
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -432,6 +466,18 @@ class GuiProjectDetailsContents(QWidget):
|
|||||||
# Slots
|
# Slots
|
||||||
##
|
##
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def _novelValueChanged(self):
|
||||||
|
"""Refresh the tree with another root item.
|
||||||
|
"""
|
||||||
|
rootHandle = self.novelValue.currentData()
|
||||||
|
if rootHandle != self._currentRoot:
|
||||||
|
self._prepareData(rootHandle)
|
||||||
|
self._populateTree()
|
||||||
|
self._currentRoot = rootHandle
|
||||||
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
def _populateTree(self):
|
def _populateTree(self):
|
||||||
"""Set the content of the chapter/page tree.
|
"""Set the content of the chapter/page tree.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -709,16 +709,16 @@ def testCoreIndex_ExtractData(mockGUI, fncDir, mockRnd):
|
|||||||
assert theIndex.getNovelTitleCounts(skipExcl=True) == [0, 1, 2, 3, 0]
|
assert theIndex.getNovelTitleCounts(skipExcl=True) == [0, 1, 2, 3, 0]
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
assert theIndex.getTableOfContents(0, skipExcl=True) == []
|
assert theIndex.getTableOfContents("0000000000010", 0, skipExcl=True) == []
|
||||||
assert theIndex.getTableOfContents(1, skipExcl=True) == [
|
assert theIndex.getTableOfContents("0000000000010", 1, skipExcl=True) == [
|
||||||
("0000000000014:T000001", 1, "New Novel", 15),
|
("0000000000014:T000001", 1, "New Novel", 15),
|
||||||
]
|
]
|
||||||
assert theIndex.getTableOfContents(2, skipExcl=True) == [
|
assert theIndex.getTableOfContents("0000000000010", 2, skipExcl=True) == [
|
||||||
("0000000000014:T000001", 1, "New Novel", 5),
|
("0000000000014:T000001", 1, "New Novel", 5),
|
||||||
("0000000000016:T000001", 2, "New Chapter", 4),
|
("0000000000016:T000001", 2, "New Chapter", 4),
|
||||||
("%s:T000001" % hHandle, 2, "Chapter One", 6),
|
("%s:T000001" % hHandle, 2, "Chapter One", 6),
|
||||||
]
|
]
|
||||||
assert theIndex.getTableOfContents(3, skipExcl=True) == [
|
assert theIndex.getTableOfContents("0000000000010", 3, skipExcl=True) == [
|
||||||
("0000000000014:T000001", 1, "New Novel", 5),
|
("0000000000014:T000001", 1, "New Novel", 5),
|
||||||
("0000000000016:T000001", 2, "New Chapter", 2),
|
("0000000000016:T000001", 2, "New Chapter", 2),
|
||||||
("0000000000017:T000001", 3, "New Scene", 2),
|
("0000000000017:T000001", 3, "New Scene", 2),
|
||||||
@@ -727,8 +727,8 @@ def testCoreIndex_ExtractData(mockGUI, fncDir, mockRnd):
|
|||||||
("%s:T000001" % tHandle, 3, "Scene Two", 2),
|
("%s:T000001" % tHandle, 3, "Scene Two", 2),
|
||||||
]
|
]
|
||||||
|
|
||||||
assert theIndex.getTableOfContents(0, skipExcl=False) == []
|
assert theIndex.getTableOfContents("0000000000010", 0, skipExcl=False) == []
|
||||||
assert theIndex.getTableOfContents(1, skipExcl=False) == [
|
assert theIndex.getTableOfContents("0000000000010", 1, skipExcl=False) == [
|
||||||
("0000000000014:T000001", 1, "New Novel", 9),
|
("0000000000014:T000001", 1, "New Novel", 9),
|
||||||
("%s:T000001" % nHandle, 1, "Hello World!", 12),
|
("%s:T000001" % nHandle, 1, "Hello World!", 12),
|
||||||
("%s:T000011" % nHandle, 1, "Hello World!", 22),
|
("%s:T000011" % nHandle, 1, "Hello World!", 22),
|
||||||
|
|||||||
Reference in New Issue
Block a user