From 06031ab7d52467f9107b5cba3a6caf6b4cd1d483 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sun, 1 Dec 2019 16:26:37 +0100
Subject: [PATCH 01/14] Started adding split amd merge functions
---
nw/project/project.py | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/nw/project/project.py b/nw/project/project.py
index 041029a1..2a88333b 100644
--- a/nw/project/project.py
+++ b/nw/project/project.py
@@ -369,6 +369,39 @@ class NWProject():
self.clearProject()
return True
+ ##
+ # Document Methods
+ ##
+
+ def splitDocument(self, tHandle, headerLevel, folderLevel):
+ """Split a document into multiple documents under the same
+ header. Header level threshold determines at what level the
+ splitting should occur, and folders can also be created at a
+ certain structure level.
+ """
+
+ return True
+
+ def mergeDocuments(self, handleList):
+ """Merge a list of document handles into a single document.
+ """
+
+ fileList = []
+ for tHandle in handleList:
+ tItem = self.getItem(tHandle)
+ if tItem is None:
+ continue
+ if tItem.itemType == nwItemType.FILE:
+ fileList.append(tHandle)
+ else:
+ pass
+
+ mergeText = ""
+ for tHandle in fileList:
+ pass
+
+ return True
+
##
# Set Functions
##
From a111247a3c3a73572916c5b95e9744e4673fc09b Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Tue, 21 Jan 2020 11:51:49 +0100
Subject: [PATCH 02/14] Added split and merge icons
---
.../graphics/{export.txt => license.txt} | 5 +++
nw/assets/graphics/merge.svg | 31 +++++++++++++++++++
nw/assets/graphics/split.svg | 31 +++++++++++++++++++
3 files changed, 67 insertions(+)
rename nw/assets/graphics/{export.txt => license.txt} (75%)
create mode 100644 nw/assets/graphics/merge.svg
create mode 100644 nw/assets/graphics/split.svg
diff --git a/nw/assets/graphics/export.txt b/nw/assets/graphics/license.txt
similarity index 75%
rename from nw/assets/graphics/export.txt
rename to nw/assets/graphics/license.txt
index 1a65e8da..8a822fd2 100644
--- a/nw/assets/graphics/export.txt
+++ b/nw/assets/graphics/license.txt
@@ -1,3 +1,8 @@
FROM ICON SET: Typicons
LICENSE: Creative Commons (Attribution-Share Alike 3.0 Unported)
https://creativecommons.org/licenses/by-sa/3.0/
+
+Apllies to:
+export.svg
+merge.svg
+split.svg
diff --git a/nw/assets/graphics/merge.svg b/nw/assets/graphics/merge.svg
new file mode 100644
index 00000000..1b4c6ae9
--- /dev/null
+++ b/nw/assets/graphics/merge.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/graphics/split.svg b/nw/assets/graphics/split.svg
new file mode 100644
index 00000000..c427eea6
--- /dev/null
+++ b/nw/assets/graphics/split.svg
@@ -0,0 +1,31 @@
+
+
From 6cac679458ecdab38873cd379589bdf5f1b77457 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Thu, 23 Jan 2020 15:52:27 +0100
Subject: [PATCH 03/14] Added merge documents dialog and related code
---
nw/constants/constants.py | 1 +
nw/gui/__init__.py | 2 +
nw/gui/dialogs/__init__.py | 2 +
nw/gui/dialogs/docmerge.py | 108 +++++++++++++++++++++++++++++++++++++
nw/gui/icons.py | 2 +
nw/gui/mainmenu.py | 7 +++
nw/guimain.py | 13 ++++-
7 files changed, 134 insertions(+), 1 deletion(-)
create mode 100644 nw/gui/dialogs/docmerge.py
diff --git a/nw/constants/constants.py b/nw/constants/constants.py
index a0325482..d3ccd1c7 100644
--- a/nw/constants/constants.py
+++ b/nw/constants/constants.py
@@ -29,6 +29,7 @@ class nwFiles():
EXPORT_OPT = "exportOptions.json"
TLINE_OPT = "timelineOptions.json"
SLOG_OPT = "sessionLogOptions.json"
+ MERGE_OPT = "docMergeOptions.json"
# END Class nwFiles
diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py
index b8196cc2..fad7b148 100644
--- a/nw/gui/__init__.py
+++ b/nw/gui/__init__.py
@@ -8,6 +8,7 @@ from nw.gui.theme import GuiTheme
# Dialogs
from nw.gui.dialogs.configeditor import GuiConfigEditor
+from nw.gui.dialogs.docmerge import GuiDocMerge
from nw.gui.dialogs.export import GuiExport
from nw.gui.dialogs.itemeditor import GuiItemEditor
from nw.gui.dialogs.projecteditor import GuiProjectEditor
@@ -33,6 +34,7 @@ __all__ = [
"GuiMainStatus",
"GuiTheme",
"GuiConfigEditor",
+ "GuiDocMerge",
"GuiExport",
"GuiItemEditor",
"GuiProjectEditor",
diff --git a/nw/gui/dialogs/__init__.py b/nw/gui/dialogs/__init__.py
index fac299ba..0c6b842e 100644
--- a/nw/gui/dialogs/__init__.py
+++ b/nw/gui/dialogs/__init__.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from nw.gui.dialogs.configeditor import GuiConfigEditor
+from nw.gui.dialogs.docmerge import GuiDocMerge
from nw.gui.dialogs.export import GuiExport
from nw.gui.dialogs.itemeditor import GuiItemEditor
from nw.gui.dialogs.projecteditor import GuiProjectEditor
@@ -9,6 +10,7 @@ from nw.gui.dialogs.timelineview import GuiTimeLineView
__all__ = [
"GuiConfigEditor",
+ "GuiDocMerge",
"GuiExport",
"GuiItemEditor",
"GuiProjectEditor",
diff --git a/nw/gui/dialogs/docmerge.py b/nw/gui/dialogs/docmerge.py
new file mode 100644
index 00000000..264fc703
--- /dev/null
+++ b/nw/gui/dialogs/docmerge.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+"""novelWriter GUI Doc Merge
+
+ novelWriter – GUI Doc Merge
+=============================
+ Tool for merging multiple documents to one
+
+ File History:
+ Created: 2020-01-23 [0.4.3]
+
+"""
+
+import logging
+import nw
+
+from PyQt5.QtCore import Qt
+from PyQt5.QtWidgets import (
+ QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QLabel,
+ QProgressBar
+)
+
+from nw.tools import OptLastState
+from nw.constants import nwFiles
+
+logger = logging.getLogger(__name__)
+
+class GuiDocMerge(QDialog):
+
+ def __init__(self, theParent, theProject):
+ QDialog.__init__(self, theParent)
+
+ logger.debug("Initialising GuiDocMerge ...")
+
+ self.mainConf = nw.CONFIG
+ self.theParent = theParent
+ self.theProject = theProject
+ self.optState = DocMergeLastState(self.theProject,nwFiles.MERGE_OPT)
+ self.optState.loadSettings()
+
+ self.outerBox = QHBoxLayout()
+ self.innerBox = QVBoxLayout()
+ self.setWindowTitle("Merge Documents")
+ self.setLayout(self.outerBox)
+
+ self.guiDeco = self.theParent.theTheme.loadDecoration("merge",(64,64))
+
+ self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
+ self.outerBox.addLayout(self.innerBox)
+
+ self.doMergeForm = QGridLayout()
+ self.doMergeForm.setContentsMargins(10,5,0,10)
+
+ self.mergeButton = QPushButton("Merge")
+ self.mergeButton.clicked.connect(self._doMerge)
+
+ self.closeButton = QPushButton("Close")
+ self.closeButton.clicked.connect(self._doClose)
+
+ self.mergeStatus = QLabel("Ready ...")
+ self.mergeProgress = QProgressBar(self)
+
+ self.doMergeForm.addWidget(self.mergeStatus, 0, 0, 1, 3)
+ self.doMergeForm.addWidget(self.mergeProgress, 1, 0)
+ self.doMergeForm.addWidget(self.mergeButton, 1, 1)
+ self.doMergeForm.addWidget(self.closeButton, 1, 2)
+
+ self.innerBox.addLayout(self.doMergeForm)
+
+ self.rejected.connect(self._doClose)
+ self.show()
+
+ logger.debug("GuiDocMerge initialisation complete")
+
+ return
+
+ ##
+ # Buttons
+ ##
+
+ def _doMerge(self):
+
+ logger.verbose("GuiDocMerge merge button clicked")
+
+ return
+
+ def _doClose(self):
+
+ logger.verbose("GuiDocMerge close button clicked")
+
+ self.optState.saveSettings()
+ self.close()
+
+ return
+
+# END Class GuiDocMerge
+
+class DocMergeLastState(OptLastState):
+
+ def __init__(self, theProject, theFile):
+ OptLastState.__init__(self, theProject, theFile)
+ self.theState = {
+ }
+ self.stringOpt = ()
+ self.boolOpt = ()
+ self.intOpt = ()
+ return
+
+# END Class DocMergeLastState
diff --git a/nw/gui/icons.py b/nw/gui/icons.py
index 88149b6e..facb84d7 100644
--- a/nw/gui/icons.py
+++ b/nw/gui/icons.py
@@ -46,7 +46,9 @@ class GuiIcons:
DECO_MAP = {
"export" : "export.svg",
+ "merge" : "merge.svg",
"settings" : "gear.svg",
+ "split" : "split.svg",
}
def __init__(self, theParent):
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index ae5df846..061b5e2d 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -369,6 +369,13 @@ class GuiMainMenu(QMenuBar):
self.aImportFile.triggered.connect(self.theParent.importDocument)
self.docuMenu.addAction(self.aImportFile)
+ # Document > Merge Documents
+ self.aMergeDocs = QAction("Merge Documents", self)
+ self.aMergeDocs.setStatusTip("Merge multiple documents")
+ # self.aMergeDocs.setShortcut("Ctrl+Shift+I")
+ self.aMergeDocs.triggered.connect(self.theParent.mergeDocuments)
+ self.docuMenu.addAction(self.aMergeDocs)
+
return
def _buildViewMenu(self):
diff --git a/nw/guimain.py b/nw/guimain.py
index 63a31795..4572ee01 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -27,7 +27,7 @@ from nw.gui import (
GuiMainMenu, GuiMainStatus, GuiTheme, GuiDocTree, GuiDocEditor,
GuiDocViewer, GuiDocDetails, GuiSearchBar, GuiNoticeBar,
GuiDocViewDetails, GuiConfigEditor, GuiProjectEditor, GuiExport,
- GuiItemEditor, GuiTimeLineView, GuiSessionLogView
+ GuiItemEditor, GuiTimeLineView, GuiSessionLogView, GuiDocMerge
)
from nw.project import NWProject, NWDoc, NWItem, NWIndex, NWBackup
from nw.tools import countWords
@@ -458,6 +458,17 @@ class GuiMain(QMainWindow):
return True
+ def mergeDocuments(self):
+ """Merge multiple documents to one single new document.
+ """
+
+ if self.mainConf.showGUI:
+ dlgMerge = GuiDocMerge(self, self.theProject)
+ if dlgMerge.exec_():
+ pass
+
+ return True
+
def passDocumentAction(self, theAction):
"""Pass on document action theAction to whatever document has
the focus. If no document has focus, the action is discarded.
From 6b79b7a42395c53e465e15cdf629665bc834317f Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 31 Jan 2020 17:17:07 +0100
Subject: [PATCH 04/14] Merging a folder of documents into one file now works
---
nw/gui/dialogs/docmerge.py | 78 +++++++++++++++++++++++++++++++++-----
nw/gui/elements/doctree.py | 25 ++++++++++--
2 files changed, 89 insertions(+), 14 deletions(-)
diff --git a/nw/gui/dialogs/docmerge.py b/nw/gui/dialogs/docmerge.py
index 264fc703..503eba44 100644
--- a/nw/gui/dialogs/docmerge.py
+++ b/nw/gui/dialogs/docmerge.py
@@ -16,11 +16,11 @@ import nw
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QLabel,
- QProgressBar
+ QProgressBar, QListWidget, QAbstractItemView, QListWidgetItem
)
-
+from nw.constants import nwFiles, nwAlert, nwItemClass, nwItemType
+from nw.project import NWDoc
from nw.tools import OptLastState
-from nw.constants import nwFiles
logger = logging.getLogger(__name__)
@@ -34,6 +34,7 @@ class GuiDocMerge(QDialog):
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject
+ self.sourceItem = None
self.optState = DocMergeLastState(self.theProject,nwFiles.MERGE_OPT)
self.optState.loadSettings()
@@ -50,25 +51,26 @@ class GuiDocMerge(QDialog):
self.doMergeForm = QGridLayout()
self.doMergeForm.setContentsMargins(10,5,0,10)
+ self.listBox = QListWidget()
+ self.listBox.setDragDropMode(QAbstractItemView.InternalMove)
+
self.mergeButton = QPushButton("Merge")
self.mergeButton.clicked.connect(self._doMerge)
self.closeButton = QPushButton("Close")
self.closeButton.clicked.connect(self._doClose)
- self.mergeStatus = QLabel("Ready ...")
- self.mergeProgress = QProgressBar(self)
-
- self.doMergeForm.addWidget(self.mergeStatus, 0, 0, 1, 3)
- self.doMergeForm.addWidget(self.mergeProgress, 1, 0)
- self.doMergeForm.addWidget(self.mergeButton, 1, 1)
- self.doMergeForm.addWidget(self.closeButton, 1, 2)
+ self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3)
+ self.doMergeForm.addWidget(self.mergeButton, 1, 1)
+ self.doMergeForm.addWidget(self.closeButton, 1, 2)
self.innerBox.addLayout(self.doMergeForm)
self.rejected.connect(self._doClose)
self.show()
+ self._populateList()
+
logger.debug("GuiDocMerge initialisation complete")
return
@@ -81,6 +83,31 @@ class GuiDocMerge(QDialog):
logger.verbose("GuiDocMerge merge button clicked")
+ finalOrder = []
+ for i in range(self.listBox.count()):
+ finalOrder.append(self.listBox.item(i).data(Qt.UserRole))
+
+ theDoc = NWDoc(self.theProject, self.theParent)
+ theText = ""
+ for tHandle in finalOrder:
+ theText += theDoc.openDocument(tHandle, False).rstrip()
+ theText += "\n\n"
+
+ if self.sourceItem is None:
+ self.theParent.makeAlert((
+ "Cannot parse source item."
+ ), nwAlert.ERROR)
+ return
+
+ srcItem = self.theProject.getItem(self.sourceItem)
+ nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
+ self.theParent.treeView.revealTreeItem(nHandle)
+ theDoc.openDocument(nHandle, False)
+ theDoc.saveDocument(theText)
+ self.theParent.openDocument(nHandle)
+
+ self.close()
+
return
def _doClose(self):
@@ -92,6 +119,37 @@ class GuiDocMerge(QDialog):
return
+ ##
+ # Internal Functions
+ ##
+
+ def _populateList(self):
+
+ tHandle = self.theParent.treeView.getSelectedHandle()
+ self.sourceItem = tHandle
+ if tHandle is None:
+ return
+
+ nwItem = self.theProject.getItem(tHandle)
+ if nwItem is None:
+ return
+ if nwItem.itemType is not nwItemType.FOLDER:
+ self.theParent.makeAlert((
+ "Element selected in the project tree must be a folder."
+ ), nwAlert.ERROR)
+ return
+
+ for sHandle in self.theParent.treeView.getTreeFromHandle(tHandle):
+ newItem = QListWidgetItem()
+ nwItem = self.theProject.getItem(sHandle)
+ if nwItem.itemType is not nwItemType.FILE:
+ continue
+ newItem.setText(nwItem.itemName)
+ newItem.setData(Qt.UserRole, sHandle)
+ self.listBox.addItem(newItem)
+
+ return
+
# END Class GuiDocMerge
class DocMergeLastState(OptLastState):
diff --git a/nw/gui/elements/doctree.py b/nw/gui/elements/doctree.py
index d5b9fb4f..63a998dd 100644
--- a/nw/gui/elements/doctree.py
+++ b/nw/gui/elements/doctree.py
@@ -171,14 +171,21 @@ class GuiDocTree(QTreeWidget):
return False
# Add the new item to the tree
- nwItem = self.theProject.getItem(tHandle)
- trItem = self._addTreeItem(nwItem)
+ self.revealTreeItem(tHandle)
+ self.theParent.editItem()
+
+ return True
+
+ def revealTreeItem(self, tHandle):
+ """Reveal a newly added project item in the project tree.
+ """
+ nwItem = self.theProject.getItem(tHandle)
+ trItem = self._addTreeItem(nwItem)
+ pHandle = nwItem.parHandle
if pHandle is not None and pHandle in self.theMap.keys():
self.theMap[pHandle].setExpanded(True)
self.clearSelection()
trItem.setSelected(True)
- self.theParent.editItem()
-
return True
def moveTreeItem(self, nStep):
@@ -221,6 +228,16 @@ class GuiDocTree(QTreeWidget):
self.theProject.setTreeOrder(theList)
return True
+ def getTreeFromHandle(self, tHandle):
+ """Recursively return all the children items starting from a
+ given item handle.
+ """
+ theList = []
+ theItem = self._getTreeItem(tHandle)
+ if theItem is not None:
+ theList = self._scanChildren(theList, theItem, 0)
+ return theList
+
def getColumnSizes(self):
retVals = [
self.columnWidth(0),
From 605541c87dc440cfbc0fa0885f5653ff10472e3f Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 1 Feb 2020 12:49:45 +0100
Subject: [PATCH 05/14] Some cleanup of the merge document dialog
---
nw/gui/dialogs/docmerge.py | 37 ++++++++++++++-----------------------
1 file changed, 14 insertions(+), 23 deletions(-)
diff --git a/nw/gui/dialogs/docmerge.py b/nw/gui/dialogs/docmerge.py
index 503eba44..2b46eba5 100644
--- a/nw/gui/dialogs/docmerge.py
+++ b/nw/gui/dialogs/docmerge.py
@@ -15,12 +15,11 @@ import nw
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
- QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QLabel,
- QProgressBar, QListWidget, QAbstractItemView, QListWidgetItem
+ QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton,
+ QListWidget, QAbstractItemView, QListWidgetItem
)
-from nw.constants import nwFiles, nwAlert, nwItemClass, nwItemType
+from nw.constants import nwAlert, nwItemType
from nw.project import NWDoc
-from nw.tools import OptLastState
logger = logging.getLogger(__name__)
@@ -35,8 +34,6 @@ class GuiDocMerge(QDialog):
self.theParent = theParent
self.theProject = theProject
self.sourceItem = None
- self.optState = DocMergeLastState(self.theProject,nwFiles.MERGE_OPT)
- self.optState.loadSettings()
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
@@ -80,6 +77,10 @@ class GuiDocMerge(QDialog):
##
def _doMerge(self):
+ """Perform the merge of the files in the selected folder, and
+ create a new file in the same parent folder. The old files are
+ not removed in the merge process, and must be deleted manually.
+ """
logger.verbose("GuiDocMerge merge button clicked")
@@ -111,12 +112,10 @@ class GuiDocMerge(QDialog):
return
def _doClose(self):
-
+ """Close the dialog window without doing anything.
+ """
logger.verbose("GuiDocMerge close button clicked")
-
- self.optState.saveSettings()
self.close()
-
return
##
@@ -124,6 +123,11 @@ class GuiDocMerge(QDialog):
##
def _populateList(self):
+ """Get the item selected in the tree, check that it is a folder,
+ and try to find all files associated with it. The valid files
+ are then added to the list view in order. The list itself can be
+ reordered by the user.
+ """
tHandle = self.theParent.treeView.getSelectedHandle()
self.sourceItem = tHandle
@@ -151,16 +155,3 @@ class GuiDocMerge(QDialog):
return
# END Class GuiDocMerge
-
-class DocMergeLastState(OptLastState):
-
- def __init__(self, theProject, theFile):
- OptLastState.__init__(self, theProject, theFile)
- self.theState = {
- }
- self.stringOpt = ()
- self.boolOpt = ()
- self.intOpt = ()
- return
-
-# END Class DocMergeLastState
From f937ebc396e956a3b251e2d7bf6f9f42599cbccb Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 1 Feb 2020 14:10:48 +0100
Subject: [PATCH 06/14] Added code to permanently delete project documents
---
nw/gui/elements/doctree.py | 69 ++++++++++++++++++++++++++++++++------
nw/gui/mainmenu.py | 4 +--
nw/project/document.py | 35 ++++++++++++++-----
nw/project/project.py | 50 ++++++---------------------
4 files changed, 96 insertions(+), 62 deletions(-)
diff --git a/nw/gui/elements/doctree.py b/nw/gui/elements/doctree.py
index 63a998dd..30a369e1 100644
--- a/nw/gui/elements/doctree.py
+++ b/nw/gui/elements/doctree.py
@@ -16,10 +16,10 @@ import nw
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QFont, QColor
from PyQt5.QtWidgets import (
- QTreeWidget, QTreeWidgetItem, QAbstractItemView, QApplication
+ QTreeWidget, QTreeWidgetItem, QAbstractItemView, QApplication, QMessageBox
)
-from nw.project import NWItem
+from nw.project import NWItem, NWDoc
from nw.constants import (
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert
)
@@ -263,21 +263,65 @@ class GuiDocTree(QTreeWidget):
trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.getItem(tHandle)
+ if nwItemS is None:
+ return False
+
if nwItemS.itemType == nwItemType.FILE:
logger.debug("User requested file %s moved to trash" % tHandle)
trItemP = trItemS.parent()
trItemT = self._addTrashRoot()
if trItemP is None or trItemT is None:
- logger.error("Could not move item to trash")
+ logger.error("Could not delete item")
return False
- tIndex = trItemP.indexOfChild(trItemS)
- trItemC = trItemP.takeChild(tIndex)
- trItemT.addChild(trItemC)
- nwItemS.setParent(self.theProject.trashRoot)
- self.clearSelection()
- trItemP.setSelected(True)
- self.theProject.setProjectChanged(True)
- self.theParent.theIndex.deleteHandle(tHandle)
+
+ pHandle = nwItemS.parHandle
+ if pHandle is not None and pHandle == self.theProject.trashRoot:
+ # If the file is in the trash folder already, as the
+ # user if they want to permanently delete the file.
+
+ doPermanent = False
+ if self.mainConf.showGUI:
+ msgBox = QMessageBox()
+ msgRes = msgBox.question(
+ self, "Delete File", "Permanently delete file '%s'?" % nwItemS.itemName
+ )
+ if msgRes == QMessageBox.Yes:
+ doPermanent = True
+ else:
+ doPermanent = True
+
+ if doPermanent:
+ logger.debug("Permanently deleting file with handle %s" % tHandle)
+
+ tIndex = trItemP.indexOfChild(trItemS)
+ trItemC = trItemP.takeChild(tIndex)
+ self.clearSelection()
+ trItemP.setSelected(True)
+
+ if self.theParent.docEditor.theHandle == tHandle:
+ self.theParent.closeDocument()
+
+ theDoc = NWDoc(self.theProject, self.theParent)
+ theDoc.deleteDocument(tHandle)
+ self.theProject.deleteItem(tHandle)
+ self.theParent.theIndex.deleteHandle(tHandle)
+
+ else:
+ # The file is not already in the trash folder, so we
+ # move it there.
+
+ if pHandle is None:
+ logger.warning("File has no parent item")
+
+ tIndex = trItemP.indexOfChild(trItemS)
+ trItemC = trItemP.takeChild(tIndex)
+ trItemT.addChild(trItemC)
+ nwItemS.setParent(self.theProject.trashRoot)
+ self.clearSelection()
+ trItemP.setSelected(True)
+
+ self.theProject.setProjectChanged(True)
+ self.theParent.theIndex.deleteHandle(tHandle)
elif nwItemS.itemType == nwItemType.FOLDER:
logger.debug("User requested folder %s deleted" % tHandle)
@@ -445,6 +489,9 @@ class GuiDocTree(QTreeWidget):
return newItem
def _addTrashRoot(self):
+ """Adds the trash root folder if it doesn't already exist in the
+ project tree.
+ """
if self.theProject.trashRoot is None:
self.theProject.addTrash()
trItem = self._addTreeItem(
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index 061b5e2d..580aacaf 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -370,8 +370,8 @@ class GuiMainMenu(QMenuBar):
self.docuMenu.addAction(self.aImportFile)
# Document > Merge Documents
- self.aMergeDocs = QAction("Merge Documents", self)
- self.aMergeDocs.setStatusTip("Merge multiple documents")
+ self.aMergeDocs = QAction("Merge Folder to Document", self)
+ self.aMergeDocs.setStatusTip("Merge a folder of documents to a single document")
# self.aMergeDocs.setShortcut("Ctrl+Shift+I")
self.aMergeDocs.triggered.connect(self.theParent.mergeDocuments)
self.docuMenu.addAction(self.aMergeDocs)
diff --git a/nw/project/document.py b/nw/project/document.py
index 0cc0fa66..e2a46d65 100644
--- a/nw/project/document.py
+++ b/nw/project/document.py
@@ -59,7 +59,7 @@ class NWDoc():
if self.theItem.parHandle == self.theProject.trashRoot:
self.docEditable = False
- docDir, docFile = self._assemblePath(self.FILE_MN)
+ docDir, docFile = self.assemblePath(self.docHandle, self.FILE_MN)
self.fileLoc = path.join(docDir,docFile)
logger.debug("Opening document %s" % self.fileLoc)
dataDir = path.join(self.theProject.projPath, docDir)
@@ -92,7 +92,7 @@ class NWDoc():
if self.docHandle is None or not self.docEditable:
return False
- docDir, docFile = self._assemblePath(self.FILE_MN)
+ docDir, docFile = self.assemblePath(self.docHandle, self.FILE_MN)
logger.debug("Saving document %s" % path.join(docDir,docFile))
dataPath = path.join(self.theProject.projPath, docDir)
docPath = path.join(dataPath, docFile)
@@ -124,15 +124,32 @@ class NWDoc():
return True
- ##
- # Internal Functions
- ##
+ def deleteDocument(self, tHandle):
+ """Permanently delete a document source file and its backups
+ from the project data folder.
+ """
+ docDir, docFile = self.assemblePath(tHandle, self.FILE_MN)
+ dataPath = path.join(self.theProject.projPath, docDir)
+ chkList = []
+ chkList.append(path.join(dataPath, docFile))
+ chkList.append(path.join(dataPath,docFile[:-3]+"tmp"))
+ chkList.append(path.join(dataPath,docFile[:-3]+"bak"))
+ for chkFile in chkList:
+ if path.isfile(chkFile):
+ try:
+ unlink(chkFile)
+ logger.debug("Deleted: %s" % chkFile)
+ except Exception as e:
+ self.makeAlert(["Could not delete document file.",str(e)], nwAlert.ERROR)
+ return False
+ return True
- def _assemblePath(self, docExt):
- if self.docHandle is None:
+ @staticmethod
+ def assemblePath(tHandle, docExt):
+ if tHandle is None:
return None
- docDir = "data_"+self.docHandle[0]
- docFile = self.docHandle[1:13]+"_"+docExt
+ docDir = "data_"+tHandle[0]
+ docFile = tHandle[1:13]+"_"+docExt
return docDir, docFile
# END Class NWDoc
diff --git a/nw/project/project.py b/nw/project/project.py
index 2a88333b..a52a83f3 100644
--- a/nw/project/project.py
+++ b/nw/project/project.py
@@ -13,7 +13,7 @@
import logging
import nw
-from os import path, mkdir, listdir
+from os import path, mkdir, listdir, unlink
from shutil import copyfile
from lxml import etree
from hashlib import sha256
@@ -369,39 +369,6 @@ class NWProject():
self.clearProject()
return True
- ##
- # Document Methods
- ##
-
- def splitDocument(self, tHandle, headerLevel, folderLevel):
- """Split a document into multiple documents under the same
- header. Header level threshold determines at what level the
- splitting should occur, and folders can also be created at a
- certain structure level.
- """
-
- return True
-
- def mergeDocuments(self, handleList):
- """Merge a list of document handles into a single document.
- """
-
- fileList = []
- for tHandle in handleList:
- tItem = self.getItem(tHandle)
- if tItem is None:
- continue
- if tItem.itemType == nwItemType.FILE:
- fileList.append(tHandle)
- else:
- pass
-
- mergeText = ""
- for tHandle in fileList:
- pass
-
- return True
-
##
# Set Functions
##
@@ -485,9 +452,6 @@ class NWProject():
self.setProjectChanged(True)
return True
- def getSessionWordCount(self):
- return self.currWCount - self.lastWCount
-
def setStatusColours(self, newCols):
replaceMap = self.statusItems.setNewEntries(newCols)
if self.projTree is not None:
@@ -530,6 +494,9 @@ class NWProject():
logger.error("No tree item with handle %s" % str(tHandle))
return None
+ def getSessionWordCount(self):
+ return self.currWCount - self.lastWCount
+
def getRootItem(self, tHandle):
"""Iterate upwards in the tree until we find the item with
parent None, the root item. We do this with a for loop with a
@@ -538,10 +505,13 @@ class NWProject():
tItem = self.getItem(tHandle)
if tItem is not None:
for i in range(200):
- tHandle = tItem.parHandle
- tItem = self.getItem(tHandle)
- if tItem is None:
+ if tItem.parHandle is None:
return tHandle
+ else:
+ tHandle = tItem.parHandle
+ tItem = self.getItem(tHandle)
+ if tItem is None:
+ return tHandle
return None
def getProjectItems(self):
From 068674e63dc05cfe19b093d67095f04e348b9c78 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Tue, 4 Feb 2020 23:57:29 +0100
Subject: [PATCH 07/14] Remove the change of selected item when deleting, and
let the tree widget handle it
---
nw/gui/elements/doctree.py | 6 ------
1 file changed, 6 deletions(-)
diff --git a/nw/gui/elements/doctree.py b/nw/gui/elements/doctree.py
index 30a369e1..5ade6c5b 100644
--- a/nw/gui/elements/doctree.py
+++ b/nw/gui/elements/doctree.py
@@ -295,8 +295,6 @@ class GuiDocTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS)
trItemC = trItemP.takeChild(tIndex)
- self.clearSelection()
- trItemP.setSelected(True)
if self.theParent.docEditor.theHandle == tHandle:
self.theParent.closeDocument()
@@ -317,8 +315,6 @@ class GuiDocTree(QTreeWidget):
trItemC = trItemP.takeChild(tIndex)
trItemT.addChild(trItemC)
nwItemS.setParent(self.theProject.trashRoot)
- self.clearSelection()
- trItemP.setSelected(True)
self.theProject.setProjectChanged(True)
self.theParent.theIndex.deleteHandle(tHandle)
@@ -332,8 +328,6 @@ class GuiDocTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS)
if trItemS.childCount() == 0:
trItemP.takeChild(tIndex)
- self.clearSelection()
- trItemP.setSelected(True)
self.theProject.deleteItem(tHandle)
else:
self.makeAlert(["Cannot delete folder.","It is not empty."], nwAlert.ERROR)
From c43e121389a23931f7cb80c55edcd12ab809012a Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Tue, 4 Feb 2020 23:59:00 +0100
Subject: [PATCH 08/14] Added document split dialog and associated code
---
nw/gui/__init__.py | 2 +
nw/gui/dialogs/__init__.py | 2 +
nw/gui/dialogs/docsplit.py | 247 +++++++++++++++++++++++++++++++++++++
nw/gui/mainmenu.py | 7 +-
nw/guimain.py | 21 ++--
nw/project/project.py | 5 +
6 files changed, 275 insertions(+), 9 deletions(-)
create mode 100644 nw/gui/dialogs/docsplit.py
diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py
index fad7b148..d8842bcc 100644
--- a/nw/gui/__init__.py
+++ b/nw/gui/__init__.py
@@ -9,6 +9,7 @@ from nw.gui.theme import GuiTheme
# Dialogs
from nw.gui.dialogs.configeditor import GuiConfigEditor
from nw.gui.dialogs.docmerge import GuiDocMerge
+from nw.gui.dialogs.docsplit import GuiDocSplit
from nw.gui.dialogs.export import GuiExport
from nw.gui.dialogs.itemeditor import GuiItemEditor
from nw.gui.dialogs.projecteditor import GuiProjectEditor
@@ -35,6 +36,7 @@ __all__ = [
"GuiTheme",
"GuiConfigEditor",
"GuiDocMerge",
+ "GuiDocSplit",
"GuiExport",
"GuiItemEditor",
"GuiProjectEditor",
diff --git a/nw/gui/dialogs/__init__.py b/nw/gui/dialogs/__init__.py
index 0c6b842e..a58b4982 100644
--- a/nw/gui/dialogs/__init__.py
+++ b/nw/gui/dialogs/__init__.py
@@ -2,6 +2,7 @@
from nw.gui.dialogs.configeditor import GuiConfigEditor
from nw.gui.dialogs.docmerge import GuiDocMerge
+from nw.gui.dialogs.docsplit import GuiDocSplit
from nw.gui.dialogs.export import GuiExport
from nw.gui.dialogs.itemeditor import GuiItemEditor
from nw.gui.dialogs.projecteditor import GuiProjectEditor
@@ -11,6 +12,7 @@ from nw.gui.dialogs.timelineview import GuiTimeLineView
__all__ = [
"GuiConfigEditor",
"GuiDocMerge",
+ "GuiDocSplit",
"GuiExport",
"GuiItemEditor",
"GuiProjectEditor",
diff --git a/nw/gui/dialogs/docsplit.py b/nw/gui/dialogs/docsplit.py
new file mode 100644
index 00000000..3e8502b5
--- /dev/null
+++ b/nw/gui/dialogs/docsplit.py
@@ -0,0 +1,247 @@
+# -*- coding: utf-8 -*-
+"""novelWriter GUI Doc Split
+
+ novelWriter – GUI Doc Split
+=============================
+ Tool for splitting a single document into multiple documents
+
+ File History:
+ Created: 2020-02-01 [0.4.3]
+
+"""
+
+import logging
+import nw
+
+from PyQt5.QtCore import Qt
+from PyQt5.QtWidgets import (
+ QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QComboBox,
+ QListWidget, QAbstractItemView, QListWidgetItem
+)
+from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout
+from nw.project import NWDoc
+
+logger = logging.getLogger(__name__)
+
+class GuiDocSplit(QDialog):
+
+ def __init__(self, theParent, theProject):
+ QDialog.__init__(self, theParent)
+
+ logger.debug("Initialising GuiDocSplit ...")
+
+ self.mainConf = nw.CONFIG
+ self.theParent = theParent
+ self.theProject = theProject
+ self.sourceItem = None
+
+ self.outerBox = QHBoxLayout()
+ self.innerBox = QVBoxLayout()
+ self.setWindowTitle("Split Document")
+ self.setLayout(self.outerBox)
+
+ self.guiDeco = self.theParent.theTheme.loadDecoration("split",(64,64))
+
+ self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
+ self.outerBox.addLayout(self.innerBox)
+
+ self.doMergeForm = QGridLayout()
+ self.doMergeForm.setContentsMargins(10,5,0,10)
+
+ self.listBox = QListWidget()
+ self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+ self.splitLevel = QComboBox(self)
+ self.splitLevel.addItem("Split on Title (Level 1)", 1)
+ self.splitLevel.addItem("Split on Chapter (Level 2)", 2)
+ self.splitLevel.addItem("Split on Scene (Level 3)", 3)
+ self.splitLevel.addItem("Split on Section (Level 4)", 4)
+ self.splitLevel.setCurrentIndex(2)
+ self.splitLevel.currentIndexChanged.connect(self._populateList)
+
+ self.splitButton = QPushButton("Split")
+ self.splitButton.clicked.connect(self._doSplit)
+
+ self.closeButton = QPushButton("Close")
+ self.closeButton.clicked.connect(self._doClose)
+
+ self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3)
+ self.doMergeForm.addWidget(self.splitLevel, 1, 0, 1, 2)
+ self.doMergeForm.addWidget(self.splitButton, 2, 1)
+ self.doMergeForm.addWidget(self.closeButton, 2, 2)
+
+ self.innerBox.addLayout(self.doMergeForm)
+
+ self.rejected.connect(self._doClose)
+ self.show()
+
+ self._populateList()
+
+ logger.debug("GuiDocSplit initialisation complete")
+
+ return
+
+ ##
+ # Buttons
+ ##
+
+ def _doSplit(self):
+ """Perform the split of the file, create a new folder in the
+ same parent folder, and multiple files depending on split level
+ settings. The old file is not removed in the merge process, and
+ must be deleted manually.
+ """
+
+ logger.verbose("GuiDocSplit split button clicked")
+
+ if self.sourceItem is None:
+ self.theParent.makeAlert((
+ "No source document selected. Nothing to do."
+ ), nwAlert.ERROR)
+ return
+
+ srcItem = self.theProject.getItem(self.sourceItem)
+ if srcItem is None:
+ self.theParent.makeAlert((
+ "Could not parse source document."
+ ), nwAlert.ERROR)
+ return
+
+ theDoc = NWDoc(self.theProject, self.theParent)
+ theText = theDoc.openDocument(self.sourceItem, False)
+ theLines = theText.splitlines()
+ nLines = len(theLines)
+ theLines.insert(0, "%Split Doc")
+
+ finalOrder = []
+ for i in range(self.listBox.count()):
+ listItem = self.listBox.item(i)
+ wTitle = listItem.text()
+ lineNo = listItem.data(Qt.UserRole)
+ finalOrder.append([wTitle, lineNo, nLines])
+ if i > 0:
+ finalOrder[i-1][2] = lineNo
+
+ if len(finalOrder) == 0:
+ self.theParent.makeAlert((
+ "No headers found. Nothing to do."
+ ), nwAlert.ERROR)
+ return
+
+ fHandle = self.theProject.newFolder(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
+ self.theParent.treeView.revealTreeItem(fHandle)
+
+ for wTitle, iStart, iEnd in finalOrder:
+
+ itemLayout = nwItemLayout.NOTE
+ if srcItem.itemClass == nwItemClass.NOVEL:
+ if wTitle.startswith("# "):
+ itemLayout = nwItemLayout.PARTITION
+ elif wTitle.startswith("## "):
+ itemLayout = nwItemLayout.CHAPTER
+ elif wTitle.startswith("### "):
+ itemLayout = nwItemLayout.SCENE
+ elif wTitle.startswith("#### "):
+ itemLayout = nwItemLayout.PAGE
+
+ wTitle = wTitle.lstrip("#")
+ wTitle = wTitle.strip()
+ print(wTitle, iStart, iEnd)
+
+ nHandle = self.theProject.newFile(wTitle, srcItem.itemClass, fHandle)
+ newItem = self.theProject.getItem(nHandle)
+ newItem.setLayout(itemLayout)
+
+ theText = "\n".join(theLines[iStart:iEnd])
+ theDoc.openDocument(nHandle, False)
+ theDoc.saveDocument(theText)
+ theDoc.clearDocument()
+ self.theParent.treeView.revealTreeItem(nHandle)
+
+ # theDoc = NWDoc(self.theProject, self.theParent)
+ # theText = ""
+ # for tHandle in finalOrder:
+ # theText += theDoc.openDocument(tHandle, False).rstrip()
+ # theText += "\n\n"
+
+ # if self.sourceItem is None:
+ # self.theParent.makeAlert((
+ # "Cannot parse source item."
+ # ), nwAlert.ERROR)
+ # return
+
+ # srcItem = self.theProject.getItem(self.sourceItem)
+ # nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
+ # self.theParent.treeView.revealTreeItem(nHandle)
+ # theDoc.openDocument(nHandle, False)
+ # theDoc.saveDocument(theText)
+ # self.theParent.openDocument(nHandle)
+
+ self.close()
+
+ return
+
+ def _doClose(self):
+ """Close the dialog window without doing anything.
+ """
+ logger.verbose("GuiDocSplit close button clicked")
+ self.close()
+ return
+
+ ##
+ # Internal Functions
+ ##
+
+ def _populateList(self):
+ """Get the item selected in the tree, check that it is a folder,
+ and try to find all files associated with it. The valid files
+ are then added to the list view in order. The list itself can be
+ reordered by the user.
+ """
+
+ if self.sourceItem is None:
+ self.sourceItem = self.theParent.treeView.getSelectedHandle()
+
+ if self.sourceItem is None:
+ return
+
+ nwItem = self.theProject.getItem(self.sourceItem)
+ if nwItem is None:
+ return
+ if nwItem.itemType is not nwItemType.FILE:
+ self.theParent.makeAlert((
+ "Element selected in the project tree must be a file."
+ ), nwAlert.ERROR)
+ return
+
+ self.listBox.clear()
+ theDoc = NWDoc(self.theProject, self.theParent)
+ theText = theDoc.openDocument(self.sourceItem, False)
+
+ spLevel = self.splitLevel.currentData()
+ logger.debug("Scanning document %s for headings level <= %d" % (self.sourceItem, spLevel))
+
+ lineNo = 0
+ for aLine in theText.splitlines():
+
+ lineNo += 1
+ onLine = 0
+
+ if aLine.startswith("# ") and spLevel >= 1:
+ onLine = lineNo
+ elif aLine.startswith("## ") and spLevel >= 2:
+ onLine = lineNo
+ elif aLine.startswith("### ") and spLevel >= 3:
+ onLine = lineNo
+ elif aLine.startswith("#### ") and spLevel >= 4:
+ onLine = lineNo
+
+ if onLine > 0:
+ newItem = QListWidgetItem()
+ newItem.setText(aLine.strip())
+ newItem.setData(Qt.UserRole, onLine)
+ self.listBox.addItem(newItem)
+
+ return
+
+# END Class GuiDocSplit
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index 580aacaf..ba75e779 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -372,10 +372,15 @@ class GuiMainMenu(QMenuBar):
# Document > Merge Documents
self.aMergeDocs = QAction("Merge Folder to Document", self)
self.aMergeDocs.setStatusTip("Merge a folder of documents to a single document")
- # self.aMergeDocs.setShortcut("Ctrl+Shift+I")
self.aMergeDocs.triggered.connect(self.theParent.mergeDocuments)
self.docuMenu.addAction(self.aMergeDocs)
+ # Document > Split Document
+ self.aSplitDoc = QAction("Split Document to Folder", self)
+ self.aSplitDoc.setStatusTip("Split a document into a folder of multiple documents")
+ self.aSplitDoc.triggered.connect(self.theParent.splitDocument)
+ self.docuMenu.addAction(self.aSplitDoc)
+
return
def _buildViewMenu(self):
diff --git a/nw/guimain.py b/nw/guimain.py
index 4572ee01..bfc67115 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -24,10 +24,10 @@ from PyQt5.QtWidgets import (
)
from nw.gui import (
- GuiMainMenu, GuiMainStatus, GuiTheme, GuiDocTree, GuiDocEditor,
- GuiDocViewer, GuiDocDetails, GuiSearchBar, GuiNoticeBar,
- GuiDocViewDetails, GuiConfigEditor, GuiProjectEditor, GuiExport,
- GuiItemEditor, GuiTimeLineView, GuiSessionLogView, GuiDocMerge
+ GuiMainMenu, GuiMainStatus, GuiTheme, GuiDocTree, GuiDocEditor, GuiExport,
+ GuiDocViewer, GuiDocDetails, GuiSearchBar, GuiNoticeBar, GuiDocViewDetails,
+ GuiConfigEditor, GuiProjectEditor, GuiItemEditor, GuiTimeLineView,
+ GuiSessionLogView, GuiDocMerge, GuiDocSplit
)
from nw.project import NWProject, NWDoc, NWItem, NWIndex, NWBackup
from nw.tools import countWords
@@ -83,7 +83,7 @@ class GuiMain(QMainWindow):
# Assemble Main Window
self.treePane = QFrame()
- self.treeBox = QVBoxLayout()
+ self.treeBox = QVBoxLayout()
self.treeBox.setContentsMargins(0,0,0,0)
self.treeBox.addWidget(self.treeView)
self.treeBox.addWidget(self.treeMeta)
@@ -461,12 +461,17 @@ class GuiMain(QMainWindow):
def mergeDocuments(self):
"""Merge multiple documents to one single new document.
"""
-
if self.mainConf.showGUI:
dlgMerge = GuiDocMerge(self, self.theProject)
- if dlgMerge.exec_():
- pass
+ dlgMerge.exec_()
+ return True
+ def splitDocument(self):
+ """Split a single document into multiple documents.
+ """
+ if self.mainConf.showGUI:
+ dlgSplit = GuiDocSplit(self, self.theProject)
+ dlgSplit.exec_()
return True
def passDocumentAction(self, theAction):
diff --git a/nw/project/project.py b/nw/project/project.py
index a52a83f3..e6167eb9 100644
--- a/nw/project/project.py
+++ b/nw/project/project.py
@@ -563,6 +563,11 @@ class NWProject():
"""This only removes the item from the order list, but not from
the project tree.
"""
+ if tHandle not in self.treeOrder:
+ logger.warning(
+ "Could not remove item %s from treeOrder as it does not exist" % tHandle
+ )
+ return False
self.treeOrder.remove(tHandle)
self.setProjectChanged(True)
return True
From 643a301e2d1b82c74ad125699a30fa8df2cdb7fc Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Wed, 5 Feb 2020 00:10:29 +0100
Subject: [PATCH 09/14] Some cleanup in the new doc split dialog
---
nw/gui/dialogs/docsplit.py | 29 ++++++++---------------------
1 file changed, 8 insertions(+), 21 deletions(-)
diff --git a/nw/gui/dialogs/docsplit.py b/nw/gui/dialogs/docsplit.py
index 3e8502b5..739bb14e 100644
--- a/nw/gui/dialogs/docsplit.py
+++ b/nw/gui/dialogs/docsplit.py
@@ -66,7 +66,7 @@ class GuiDocSplit(QDialog):
self.closeButton.clicked.connect(self._doClose)
self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3)
- self.doMergeForm.addWidget(self.splitLevel, 1, 0, 1, 2)
+ self.doMergeForm.addWidget(self.splitLevel, 1, 0, 1, 3)
self.doMergeForm.addWidget(self.splitButton, 2, 1)
self.doMergeForm.addWidget(self.closeButton, 2, 2)
@@ -112,6 +112,9 @@ class GuiDocSplit(QDialog):
theLines = theText.splitlines()
nLines = len(theLines)
theLines.insert(0, "%Split Doc")
+ logger.debug(
+ "Splitting document %s with %d lines" % (self.sourceItem,nLines)
+ )
finalOrder = []
for i in range(self.listBox.count()):
@@ -130,6 +133,7 @@ class GuiDocSplit(QDialog):
fHandle = self.theProject.newFolder(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
self.theParent.treeView.revealTreeItem(fHandle)
+ logger.verbose("Creating folder %s" % fHandle)
for wTitle, iStart, iEnd in finalOrder:
@@ -146,11 +150,13 @@ class GuiDocSplit(QDialog):
wTitle = wTitle.lstrip("#")
wTitle = wTitle.strip()
- print(wTitle, iStart, iEnd)
nHandle = self.theProject.newFile(wTitle, srcItem.itemClass, fHandle)
newItem = self.theProject.getItem(nHandle)
newItem.setLayout(itemLayout)
+ logger.verbose(
+ "Creating new document %s with text from line %d to %d" % (nHandle, iStart, iEnd-1)
+ )
theText = "\n".join(theLines[iStart:iEnd])
theDoc.openDocument(nHandle, False)
@@ -158,25 +164,6 @@ class GuiDocSplit(QDialog):
theDoc.clearDocument()
self.theParent.treeView.revealTreeItem(nHandle)
- # theDoc = NWDoc(self.theProject, self.theParent)
- # theText = ""
- # for tHandle in finalOrder:
- # theText += theDoc.openDocument(tHandle, False).rstrip()
- # theText += "\n\n"
-
- # if self.sourceItem is None:
- # self.theParent.makeAlert((
- # "Cannot parse source item."
- # ), nwAlert.ERROR)
- # return
-
- # srcItem = self.theProject.getItem(self.sourceItem)
- # nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
- # self.theParent.treeView.revealTreeItem(nHandle)
- # theDoc.openDocument(nHandle, False)
- # theDoc.saveDocument(theText)
- # self.theParent.openDocument(nHandle)
-
self.close()
return
From 6cfa2853fe1d71c424612c2d81408dc3d5e3ae34 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Wed, 5 Feb 2020 01:02:18 +0100
Subject: [PATCH 10/14] trying to make travis run again
---
.travis.yml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index d40b1c68..bba7e64e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,12 +11,17 @@ addons:
- libenchant-dev
- python3-pyqt5
- python3-pyqt5.qtsvg
+ - python3-appdirs
+ - python3-lxml
+ - python3-enchant
python:
- "3.5"
- "3.7"
install:
- - pip install -r requirements.txt
+# - pip install -r requirements.txt
# - pip install pytest-faulthandler
+ - pip install latexcodec
+ - pip install pypandoc
- pip install pytest-xvfb
- pip install pytest-cov
- pip install pytest-qt
From f58b7afd43431a7672d135ef261cb94b221a7c9b Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Wed, 5 Feb 2020 01:10:01 +0100
Subject: [PATCH 11/14] trying to make travis run again
---
.travis.yml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index bba7e64e..82955733 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,19 +9,19 @@ addons:
apt:
packages:
- libenchant-dev
- - python3-pyqt5
- - python3-pyqt5.qtsvg
- - python3-appdirs
- - python3-lxml
- - python3-enchant
+# - python3-pyqt5
+# - python3-pyqt5.qtsvg
+# - python3-appdirs
+# - python3-lxml
+# - python3-enchant
python:
- "3.5"
- "3.7"
install:
-# - pip install -r requirements.txt
+ - pip install -r requirements.txt
# - pip install pytest-faulthandler
- - pip install latexcodec
- - pip install pypandoc
+# - pip install latexcodec
+# - pip install pypandoc
- pip install pytest-xvfb
- pip install pytest-cov
- pip install pytest-qt
From 5d971508426e973361430b5b186bc0f748a830bd Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Wed, 5 Feb 2020 01:13:07 +0100
Subject: [PATCH 12/14] trying to make travis run again
---
.travis.yml | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 82955733..8097a051 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,19 +9,15 @@ addons:
apt:
packages:
- libenchant-dev
-# - python3-pyqt5
-# - python3-pyqt5.qtsvg
-# - python3-appdirs
-# - python3-lxml
-# - python3-enchant
+ - python3-pyqt5
+ - python3-pyqt5.qtsvg
python:
- "3.5"
- "3.7"
install:
+ - pip install --upgrade pip
- pip install -r requirements.txt
# - pip install pytest-faulthandler
-# - pip install latexcodec
-# - pip install pypandoc
- pip install pytest-xvfb
- pip install pytest-cov
- pip install pytest-qt
From cac75abcafdeed688a2e69f5faa930137b139e99 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Wed, 5 Feb 2020 01:22:19 +0100
Subject: [PATCH 13/14] Switch ubutu distro on travis builds
---
.travis.yml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 8097a051..5958aeec 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,9 @@
os: linux
-dist: xenial
+dist: bionic
services:
- xvfb
language: python
cache: bundler
-sudo: required
addons:
apt:
packages:
@@ -13,7 +12,7 @@ addons:
- python3-pyqt5.qtsvg
python:
- "3.5"
- - "3.7"
+ - "3.8"
install:
- pip install --upgrade pip
- pip install -r requirements.txt
From 123d64bba93a2da5f49bd02e3317120fe1bd5a4e Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Wed, 5 Feb 2020 01:27:17 +0100
Subject: [PATCH 14/14] Dropping Python 3.5 support
---
.travis.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 5958aeec..de4a683a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,8 @@ addons:
- python3-pyqt5
- python3-pyqt5.qtsvg
python:
- - "3.5"
+ - "3.6"
+ - "3.7"
- "3.8"
install:
- pip install --upgrade pip