Add the core code for the DocSplitter tool
This commit is contained in:
@@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from novelwriter.core.doctools import DocMerger
|
||||
from novelwriter.core.doctools import DocMerger, DocSplitter
|
||||
from novelwriter.core.document import NWDoc
|
||||
from novelwriter.core.index import countWords
|
||||
from novelwriter.core.project import NWProject
|
||||
@@ -30,6 +30,7 @@ from novelwriter.core.tomd import ToMarkdown
|
||||
|
||||
__all__ = [
|
||||
"DocMerger",
|
||||
"DocSplitter",
|
||||
"countWords",
|
||||
"NWDoc",
|
||||
"NWProject",
|
||||
|
||||
@@ -4,7 +4,8 @@ novelWriter – Project Document Tools
|
||||
A collection of tools to create and manipulate documents
|
||||
|
||||
File History:
|
||||
Created: 2022-10-02 [2.0b1]
|
||||
Created: 2022-10-02 [2.0b1] DocMerger
|
||||
Created: 2022-10-11 [2.0b1] DocSplitter
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
||||
@@ -117,3 +118,90 @@ class DocMerger:
|
||||
return status
|
||||
|
||||
# END Class DocMerger
|
||||
|
||||
|
||||
class DocSplitter:
|
||||
|
||||
def __init__(self, theProject, sHandle):
|
||||
|
||||
self.theProject = theProject
|
||||
|
||||
self._error = ""
|
||||
self._parHandle = None
|
||||
self._srcHandle = None
|
||||
self._srcItem = None
|
||||
|
||||
self._rawData = []
|
||||
|
||||
srcItem = self.theProject.tree[sHandle]
|
||||
if srcItem is not None and srcItem.isFileType():
|
||||
self._srcHandle = sHandle
|
||||
self._srcItem = srcItem
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Methods
|
||||
##
|
||||
|
||||
def getError(self):
|
||||
"""Return any collected errors.
|
||||
"""
|
||||
return self._error
|
||||
|
||||
def setParentItem(self, pHandle):
|
||||
"""Set the item that will be the top level parent item for the
|
||||
new documents.
|
||||
"""
|
||||
self._parHandle = pHandle
|
||||
return
|
||||
|
||||
def newParentFolder(self, pHandle, folderLabel):
|
||||
"""Create a new folder that will be the top level parent item
|
||||
for the new documents.
|
||||
"""
|
||||
if self._srcItem is None:
|
||||
return None
|
||||
|
||||
newHandle = self.theProject.newFolder(folderLabel, pHandle)
|
||||
newItem = self.theProject.tree[self._parHandle]
|
||||
newItem.setStatus(self._srcItem.itemStatus)
|
||||
newItem.setImport(self._srcItem.itemImport)
|
||||
|
||||
self._parHandle = newHandle
|
||||
|
||||
return newHandle
|
||||
|
||||
def splitDocument(self, splitData, splitText):
|
||||
"""Loop through the split data record and perform the split job.
|
||||
"""
|
||||
self._rawData = []
|
||||
buffer = splitText.copy()
|
||||
for lineNo, hLevel, hLabel in reversed(splitData):
|
||||
chunk = buffer[lineNo:]
|
||||
buffer = buffer[:lineNo]
|
||||
self._rawData.insert(0, (chunk, hLevel, hLabel))
|
||||
|
||||
return True
|
||||
|
||||
def writeDocuments(self):
|
||||
"""An iterator that will write each document in the buffer, and
|
||||
return its new handle, parent handle, and sibling handle.
|
||||
"""
|
||||
nearHandle = self._parHandle
|
||||
for docText, hLevel, docLabel in self._rawData:
|
||||
|
||||
newHandle = self.theProject.newFile(docLabel, self._parHandle)
|
||||
|
||||
outDoc = NWDoc(self.theProject, newHandle)
|
||||
status = outDoc.writeDocument("\n".join(docText))
|
||||
if not status:
|
||||
self._error = outDoc.getError()
|
||||
|
||||
yield newHandle, self._parHandle, nearHandle
|
||||
|
||||
nearHandle = newHandle
|
||||
|
||||
return
|
||||
|
||||
# END Class DocSplitter
|
||||
|
||||
@@ -41,6 +41,10 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class GuiDocSplit(QDialog):
|
||||
|
||||
LINE_ROLE = Qt.UserRole
|
||||
LEVEL_ROLE = Qt.UserRole + 1
|
||||
LABEL_ROLE = Qt.UserRole + 2
|
||||
|
||||
def __init__(self, mainGui, sHandle):
|
||||
super().__init__(parent=mainGui)
|
||||
|
||||
@@ -141,7 +145,9 @@ class GuiDocSplit(QDialog):
|
||||
headerList = []
|
||||
for i in range(self.listBox.count()):
|
||||
item = self.listBox.item(i)
|
||||
headerList.append((item.text(), item.data(Qt.UserRole)))
|
||||
headerList.append(
|
||||
(item.data(self.LINE_ROLE), item.data(self.LEVEL_ROLE), item.data(self.LABEL_ROLE))
|
||||
)
|
||||
|
||||
spLevel = self.splitLevel.currentData()
|
||||
intoFolder = self.folderSwitch.isChecked()
|
||||
@@ -157,7 +163,7 @@ class GuiDocSplit(QDialog):
|
||||
pOptions.setValue("GuiDocSplit", "intoFolder", intoFolder)
|
||||
pOptions.setValue("GuiDocSplit", "docHierarchy", docHierarchy)
|
||||
|
||||
return self._data
|
||||
return self._data, self._text
|
||||
|
||||
##
|
||||
# Slots
|
||||
@@ -193,19 +199,38 @@ class GuiDocSplit(QDialog):
|
||||
for lineNo, aLine in enumerate(self._text):
|
||||
|
||||
onLine = -1
|
||||
if aLine.startswith(("# ", "#! ")) and spLevel >= 1:
|
||||
hLevel = 0
|
||||
if aLine.startswith("# ") and spLevel >= 1:
|
||||
onLine = lineNo
|
||||
elif aLine.startswith(("## ", "##! ")) and spLevel >= 2:
|
||||
hLevel = 1
|
||||
hLabel = aLine[2:].strip()
|
||||
elif aLine.startswith("## ") and spLevel >= 2:
|
||||
onLine = lineNo
|
||||
hLevel = 2
|
||||
hLabel = aLine[3:].strip()
|
||||
elif aLine.startswith("### ") and spLevel >= 3:
|
||||
onLine = lineNo
|
||||
hLevel = 3
|
||||
hLabel = aLine[4:].strip()
|
||||
elif aLine.startswith("#### ") and spLevel >= 4:
|
||||
onLine = lineNo
|
||||
hLevel = 4
|
||||
hLabel = aLine[5:].strip()
|
||||
elif aLine.startswith("#! ") and spLevel >= 1:
|
||||
onLine = lineNo
|
||||
hLevel = 1
|
||||
hLabel = aLine[3:].strip()
|
||||
elif aLine.startswith("##! ") and spLevel >= 2:
|
||||
onLine = lineNo
|
||||
hLevel = 2
|
||||
hLabel = aLine[4:].strip()
|
||||
|
||||
if onLine >= 0:
|
||||
if onLine >= 0 and hLevel > 0:
|
||||
newItem = QListWidgetItem()
|
||||
newItem.setText(aLine.strip())
|
||||
newItem.setData(Qt.UserRole, onLine)
|
||||
newItem.setData(self.LINE_ROLE, onLine)
|
||||
newItem.setData(self.LEVEL_ROLE, hLevel)
|
||||
newItem.setData(self.LABEL_ROLE, hLabel)
|
||||
self.listBox.addItem(newItem)
|
||||
|
||||
return True
|
||||
|
||||
@@ -40,6 +40,7 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
|
||||
from novelwriter.core import DocMerger
|
||||
from novelwriter.core.doctools import DocSplitter
|
||||
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||
from novelwriter.dialogs import GuiDocMerge, GuiDocSplit, GuiEditLabel
|
||||
from novelwriter.constants import nwHeaders, trConst, nwLabels
|
||||
@@ -1475,7 +1476,18 @@ class GuiProjectTree(QTreeWidget):
|
||||
|
||||
if dlgSplit.result() == QDialog.Accepted:
|
||||
|
||||
print(dlgSplit.getData())
|
||||
splitData, splitText = dlgSplit.getData()
|
||||
print(splitData)
|
||||
|
||||
headerList = splitData.get("headerList", [])
|
||||
|
||||
docSplit = DocSplitter(self.theProject, tHandle)
|
||||
docSplit.setParentItem(tItem.itemParent)
|
||||
docSplit.splitDocument(headerList, splitText)
|
||||
|
||||
for dHandle, _, nHandle in docSplit.writeDocuments():
|
||||
self.mainGui.projView.revealNewTreeItem(dHandle, nHandle)
|
||||
self._alertTreeChange(dHandle, flush=False)
|
||||
|
||||
else:
|
||||
logger.info("Action cancelled by user")
|
||||
|
||||
Reference in New Issue
Block a user