Populate the add button menu in the project widget

This commit is contained in:
Veronica Berglyd Olsen
2022-06-06 22:03:42 +02:00
parent 12a7ec7fe3
commit 46bb8e5bcc
10 changed files with 180 additions and 86 deletions
-5
View File
@@ -502,11 +502,6 @@ class NWIndex:
""" """
return self._itemIndex.mainItemHeader(tHandle) return self._itemIndex.mainItemHeader(tHandle)
def getHandleHeaderIntLevel(self, tHandle):
"""Get the integer header level of the first header of a handle.
"""
return H_LEVEL.get(self._itemIndex.mainItemHeader(tHandle), 0)
def getTableOfContents(self, maxDepth, skipExcl=True): def getTableOfContents(self, maxDepth, skipExcl=True):
"""Generate a table of contents up to a maximum depth. """Generate a table of contents up to a maximum depth.
""" """
+119 -39
View File
@@ -37,13 +37,13 @@ from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction, QFrame, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction, QFrame,
QDialog, QHeaderView, QWidget, QVBoxLayout, QToolBar, QLabel, QToolButton, QDialog, QHeaderView, QWidget, QVBoxLayout, QToolBar, QLabel, QToolButton,
QSizePolicy QSizePolicy, QInputDialog
) )
from novelwriter.core import NWDoc from novelwriter.core import NWDoc
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.common import minmax
from novelwriter.dialogs.itemeditor import GuiItemEditor from novelwriter.dialogs.itemeditor import GuiItemEditor
from novelwriter.constants import trConst, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -82,6 +82,8 @@ class GuiProjectWiew(QWidget):
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
# Connect Signals
# Function Mappings # Function Mappings
self.newTreeItem = self.projTree.newTreeItem self.newTreeItem = self.projTree.newTreeItem
self.revealNewTreeItem = self.projTree.revealNewTreeItem self.revealNewTreeItem = self.projTree.revealNewTreeItem
@@ -139,12 +141,19 @@ class GuiProjectWiew(QWidget):
class GuiProjectToolBar(QToolBar): class GuiProjectToolBar(QToolBar):
ADD_PLAIN = 0
ADD_CHAP = 1
ADD_SCENE = 2
ADD_NOTE = 3
ADD_FOLDER = 4
def __init__(self, theWidget): def __init__(self, theWidget):
QTreeWidget.__init__(self, theWidget) QTreeWidget.__init__(self, theWidget)
logger.debug("Initialising GuiProjectToolBar ...") logger.debug("Initialising GuiProjectToolBar ...")
self.mainConf = novelwriter.CONFIG self.mainConf = novelwriter.CONFIG
self.theWidget = theWidget
self.theParent = theWidget.theParent self.theParent = theWidget.theParent
self.theProject = theWidget.theParent.theProject self.theProject = theWidget.theParent.theProject
self.theTheme = theWidget.theParent.theTheme self.theTheme = theWidget.theParent.theTheme
@@ -157,14 +166,49 @@ class GuiProjectToolBar(QToolBar):
self.setContentsMargins(0, 0, 0, 0) self.setContentsMargins(0, 0, 0, 0)
self.setStyleSheet("QToolBar {border: 0px;}") self.setStyleSheet("QToolBar {border: 0px;}")
# Novel Selector # Tree Label
self.projLabel = QLabel(self.tr("Project")) self.projLabel = QLabel(self.tr("Project"))
self.projLabel.setContentsMargins(0, 0, mPx, 0) self.projLabel.setContentsMargins(0, 0, mPx, 0)
self.projLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.projLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# Itemss Menu # Items Menu
self.mItems = QMenu()
self.aAddEmpty = self.mItems.addAction(self.tr("Plain Document"))
self.aAddEmpty.setIcon(self.theTheme.getIcon("proj_document"))
self.aAddEmpty.triggered.connect(lambda: self._forwardNewItem(self.ADD_PLAIN))
self.aAddChap = self.mItems.addAction(self.tr("Chapter Document"))
self.aAddChap.setIcon(self.theTheme.getIcon("proj_chapter"))
self.aAddChap.triggered.connect(lambda: self._forwardNewItem(self.ADD_CHAP))
self.aAddScene = self.mItems.addAction(self.tr("Scene Document"))
self.aAddScene.setIcon(self.theTheme.getIcon("proj_scene"))
self.aAddScene.triggered.connect(lambda: self._forwardNewItem(self.ADD_SCENE))
self.aAddNote = self.mItems.addAction(self.tr("Project Note"))
self.aAddNote.setIcon(self.theTheme.getIcon("proj_note"))
self.aAddNote.triggered.connect(lambda: self._forwardNewItem(self.ADD_NOTE))
self.aAddFolder = self.mItems.addAction(self.tr("Folder"))
self.aAddFolder.setIcon(self.theTheme.getIcon("proj_folder"))
self.aAddFolder.triggered.connect(lambda: self._forwardNewItem(self.ADD_FOLDER))
self.mAddRoot = self.mItems.addMenu(self.tr("Root Folder"))
self._addRootFolderEntry(nwItemClass.NOVEL)
self._addRootFolderEntry(nwItemClass.ARCHIVE)
self.mAddRoot.addSeparator()
self._addRootFolderEntry(nwItemClass.PLOT)
self._addRootFolderEntry(nwItemClass.CHARACTER)
self._addRootFolderEntry(nwItemClass.WORLD)
self._addRootFolderEntry(nwItemClass.ARCHIVE)
self._addRootFolderEntry(nwItemClass.OBJECT)
self._addRootFolderEntry(nwItemClass.ENTITY)
self._addRootFolderEntry(nwItemClass.CUSTOM)
self.tbItems = QToolButton(self) self.tbItems = QToolButton(self)
self.tbItems.setIcon(self.theTheme.getIcon("add")) self.tbItems.setIcon(self.theTheme.getIcon("add"))
self.tbItems.setMenu(self.mItems)
self.tbItems.setPopupMode(QToolButton.InstantPopup) self.tbItems.setPopupMode(QToolButton.InstantPopup)
# Settings Menu # Settings Menu
@@ -182,6 +226,45 @@ class GuiProjectToolBar(QToolBar):
return return
##
# Private Slots
##
@pyqtSlot(Enum)
def _forwardNewRootFolder(self, itemClass):
"""Forward the request for a new root folder to the tree.
"""
self.theWidget.projTree.newTreeItem(nwItemType.ROOT, itemClass)
return
@pyqtSlot(int)
def _forwardNewItem(self, type):
"""Forward the request for a new item of a given type.
"""
if type == self.ADD_PLAIN:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=0, isNote=False)
elif type == self.ADD_CHAP:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=2, isNote=False)
elif type == self.ADD_SCENE:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=3, isNote=False)
elif type == self.ADD_NOTE:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
elif type == self.ADD_FOLDER:
self.theWidget.projTree.newTreeItem(nwItemType.FOLDER)
return
##
# Internal Functions
##
def _addRootFolderEntry(self, itemClass):
"""Add a menu entry for a root folder of a given class.
"""
aNew = self.mAddRoot.addAction(trConst(nwLabels.CLASS_NAME[itemClass]))
aNew.setIcon(self.theTheme.getIcon(nwLabels.CLASS_ICON[itemClass]))
aNew.triggered.connect(lambda: self._forwardNewRootFolder(itemClass))
self.mAddRoot.addAction(aNew)
# END Class GuiProjectToolBar # END Class GuiProjectToolBar
@@ -291,7 +374,7 @@ class GuiProjectTree(QTreeWidget):
self._timeChanged = 0 self._timeChanged = 0
return return
def newTreeItem(self, itemType, itemClass=None): def newTreeItem(self, itemType, itemClass=None, hLevel=1, isNote=False):
"""Add new item to the tree, with a given itemType (and """Add new item to the tree, with a given itemType (and
itemClass if Root), and attach it to the selected handle. Also itemClass if Root), and attach it to the selected handle. Also
make sure the item is added in a place it can be added, and that make sure the item is added in a place it can be added, and that
@@ -334,52 +417,49 @@ class GuiProjectTree(QTreeWidget):
), nwAlert.ERROR) ), nwAlert.ERROR)
return False return False
# Ask for label
if itemType == nwItemType.FILE:
if isNote:
newLabel = self.tr("New Note")
elif hLevel == 2:
newLabel = self.tr("New Chapter")
elif hLevel == 3:
newLabel = self.tr("New Scene")
else:
newLabel = self.tr("New Document")
else:
newLabel = self.tr("New Folder")
newLabel, dlgOk = QInputDialog.getText(self, "", self.tr("Label:"), text=newLabel)
if not dlgOk:
logger.info("New item creation cancelled by user")
return False
# Add the file or folder # Add the file or folder
if itemType == nwItemType.FILE: if itemType == nwItemType.FILE:
if pItem.isNovelLike(): tHandle = self.theProject.newFile(newLabel, sHandle)
tHandle = self.theProject.newFile(self.tr("New Document"), sHandle) else:
else: tHandle = self.theProject.newFolder(newLabel, sHandle)
tHandle = self.theProject.newFile(self.tr("New Note"), sHandle)
elif itemType == nwItemType.FOLDER:
tHandle = self.theProject.newFolder(self.tr("New Folder"), sHandle)
else: else:
logger.error("Failed to add new item") logger.error("Failed to add new item")
return False return False
# If there is no handle set, return here. This is a bug # If there is no handle set, return here. This is a bug.
if tHandle is None: # pragma: no cover if tHandle is None: # pragma: no cover
logger.error("Internal error")
return True return True
# Add the new item to the tree and open the editor dialog
self.revealNewTreeItem(tHandle, nHandle)
self.editTreeItem(tHandle)
# Handle new file creation # Handle new file creation
nwItem = self.theProject.tree[tHandle] if itemType == nwItemType.FILE and hLevel > 0:
if nwItem.itemType != nwItemType.FILE: if self.theProject.writeNewFile(tHandle, hLevel, not isNote):
return True # If successful, update word count
wC = self.theProject.index.getCounts(tHandle)[1]
self.propagateCount(tHandle, wC)
self.theWidget.wordCountsChanged.emit()
# This is a new file, so let's add some content # Add the new item to the project tree
newDoc = NWDoc(self.theProject, tHandle) self.revealNewTreeItem(tHandle, nHandle)
if not newDoc.readDocument():
if nwItem.itemLayout == nwItemLayout.DOCUMENT:
iLvl = self.theProject.index.getHandleHeaderIntLevel(sHandle)
hLvl = "#"*minmax(iLvl + 1, 2, 4)
newText = f"{hLvl} {nwItem.itemName}\n\n"
else:
newText = f"# {nwItem.itemName}\n\n"
pIndex = self.theProject.index
# Save the text and index it
newDoc.writeDocument(newText)
pIndex.scanText(tHandle, newText)
# Get Word Counts
_, wC, _ = pIndex.getCounts(tHandle)
self.propagateCount(tHandle, wC)
self.theWidget.wordCountsChanged.emit()
return True return True
+5 -5
View File
@@ -1,13 +1,13 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-06-05 15:03:00"> <novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-06-06 22:02:03">
<project> <project>
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
<author>Jane Smith</author> <author>Jane Smith</author>
<author>Jay Doh</author> <author>Jay Doh</author>
<saveCount>1334</saveCount> <saveCount>1342</saveCount>
<autoCount>225</autoCount> <autoCount>227</autoCount>
<editTime>67746</editTime> <editTime>68090</editTime>
</project> </project>
<settings> <settings>
<doBackup>False</doBackup> <doBackup>False</doBackup>
@@ -15,7 +15,7 @@
<spellCheck>True</spellCheck> <spellCheck>True</spellCheck>
<spellLang>None</spellLang> <spellLang>None</spellLang>
<autoOutline>True</autoOutline> <autoOutline>True</autoOutline>
<lastEdited>a520879ca0b45</lastEdited> <lastEdited>636b6aa9b697b</lastEdited>
<lastViewed>636b6aa9b697b</lastViewed> <lastViewed>636b6aa9b697b</lastViewed>
<lastWordCount>1363</lastWordCount> <lastWordCount>1363</lastWordCount>
<novelWordCount>954</novelWordCount> <novelWordCount>954</novelWordCount>
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-05-21 17:08:21"> <novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-06-06 21:17:27">
<project> <project>
<name>New Project</name> <name>New Project</name>
<title>New Novel</title> <title>New Novel</title>
@@ -16,9 +16,9 @@
<autoOutline>True</autoOutline> <autoOutline>True</autoOutline>
<lastEdited>None</lastEdited> <lastEdited>None</lastEdited>
<lastViewed>None</lastViewed> <lastViewed>None</lastViewed>
<lastWordCount>0</lastWordCount> <lastWordCount>2</lastWordCount>
<novelWordCount>0</novelWordCount> <novelWordCount>1</novelWordCount>
<notesWordCount>0</notesWordCount> <notesWordCount>1</notesWordCount>
<autoReplace/> <autoReplace/>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
@@ -28,19 +28,19 @@
<section></section> <section></section>
</titleFormat> </titleFormat>
<status> <status>
<entry key="s000008" count="5" red="100" green="100" blue="100">New</entry> <entry key="s000008" count="7" red="100" green="100" blue="100">New</entry>
<entry key="s000009" count="0" red="200" green="50" blue="0">Note</entry> <entry key="s000009" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s00000a" count="0" red="200" green="150" blue="0">Draft</entry> <entry key="s00000a" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s00000b" count="0" red="50" green="200" blue="0">Finished</entry> <entry key="s00000b" count="0" red="50" green="200" blue="0">Finished</entry>
</status> </status>
<importance> <importance>
<entry key="i00000c" count="3" red="100" green="100" blue="100">New</entry> <entry key="i00000c" count="4" red="100" green="100" blue="100">New</entry>
<entry key="i00000d" count="0" red="200" green="50" blue="0">Minor</entry> <entry key="i00000d" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i00000e" count="0" red="200" green="150" blue="0">Major</entry> <entry key="i00000e" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i00000f" count="0" red="50" green="200" blue="0">Main</entry> <entry key="i00000f" count="0" red="50" green="200" blue="0">Main</entry>
</importance> </importance>
</settings> </settings>
<content count="10"> <content count="11">
<item handle="0000000000010" parent="None" root="0000000000010" order="0" type="ROOT" class="NOVEL"> <item handle="0000000000010" parent="None" root="0000000000010" order="0" type="ROOT" class="NOVEL">
<meta expanded="False"/> <meta expanded="False"/>
<name status="s000008" import="i00000c">Novel</name> <name status="s000008" import="i00000c">Novel</name>
@@ -73,13 +73,17 @@
<meta expanded="False" charCount="0" wordCount="0" paraCount="0" cursorPos="0"/> <meta expanded="False" charCount="0" wordCount="0" paraCount="0" cursorPos="0"/>
<name status="s000008" import="i00000c" exported="True">New Scene</name> <name status="s000008" import="i00000c" exported="True">New Scene</name>
</item> </item>
<item handle="0000000000028" parent="31489056e0916" root="None" order="0" type="FILE" class="NO_CLASS" layout="NO_LAYOUT"> <item handle="0000000000028" parent="0000000000015" root="0000000000010" order="0" type="FOLDER" class="NOVEL">
<meta expanded="False" charCount="0" wordCount="0" paraCount="0" cursorPos="0"/> <meta expanded="False"/>
<name status="None" import="None" exported="True">Hello</name> <name status="s000008" import="i00000c">Stuff</name>
</item> </item>
<item handle="0000000000029" parent="71ee45a3c0db9" root="None" order="0" type="FILE" class="NO_CLASS" layout="NO_LAYOUT"> <item handle="0000000000029" parent="0000000000015" root="0000000000010" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" charCount="0" wordCount="0" paraCount="0" cursorPos="0"/> <meta expanded="False" charCount="5" wordCount="1" paraCount="0" cursorPos="0"/>
<name status="None" import="None" exported="True">Jane</name> <name status="s000008" import="i00000c" exported="True">Hello</name>
</item>
<item handle="000000000002a" parent="0000000000012" root="0000000000012" order="0" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" charCount="4" wordCount="1" paraCount="0" cursorPos="0"/>
<name status="s000008" import="i00000c" exported="True">Jane</name>
</item> </item>
</content> </content>
</novelWriterXML> </novelWriterXML>
-3
View File
@@ -232,9 +232,6 @@ def testCoreIndex_CheckThese(mockGUI, fncDir, mockRnd):
assert theIndex.getHandleHeaderLevel(cHandle) == "H1" assert theIndex.getHandleHeaderLevel(cHandle) == "H1"
assert theIndex.getHandleHeaderLevel(nHandle) == "H1" assert theIndex.getHandleHeaderLevel(nHandle) == "H1"
assert theIndex.getHandleHeaderIntLevel(cHandle) == 1
assert theIndex.getHandleHeaderIntLevel(nHandle) == 1
assert theIndex.getHandleHeaderIntLevel("stuff") == 0
# Zero Items # Zero Items
assert theIndex.checkThese([], cItem) == [] assert theIndex.checkThese([], cItem) == []
+2 -1
View File
@@ -25,7 +25,7 @@ import pytest
from mock import causeOSError from mock import causeOSError
from tools import getGuiItem, readFile, writeFile, buildTestProject from tools import getGuiItem, readFile, writeFile, buildTestProject
from PyQt5.QtWidgets import QAction, QMessageBox, QDialog from PyQt5.QtWidgets import QAction, QMessageBox, QDialog, QInputDialog
from novelwriter.enum import nwItemType, nwWidget from novelwriter.enum import nwItemType, nwWidget
from novelwriter.dialogs import GuiDocMerge, GuiItemEditor from novelwriter.dialogs import GuiDocMerge, GuiItemEditor
@@ -39,6 +39,7 @@ def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok)
monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
# Create a new project # Create a new project
buildTestProject(nwGUI, fncProj) buildTestProject(nwGUI, fncProj)
+2 -1
View File
@@ -25,7 +25,7 @@ import pytest
from mock import causeOSError from mock import causeOSError
from tools import getGuiItem, readFile, writeFile, buildTestProject from tools import getGuiItem, readFile, writeFile, buildTestProject
from PyQt5.QtWidgets import QAction, QMessageBox, QDialog from PyQt5.QtWidgets import QAction, QMessageBox, QDialog, QInputDialog
from novelwriter.enum import nwItemType, nwWidget from novelwriter.enum import nwItemType, nwWidget
from novelwriter.dialogs import GuiDocSplit, GuiItemEditor from novelwriter.dialogs import GuiDocSplit, GuiItemEditor
@@ -40,6 +40,7 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok)
monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
# Create a new project # Create a new project
buildTestProject(nwGUI, fncProj) buildTestProject(nwGUI, fncProj)
+3 -2
View File
@@ -23,7 +23,7 @@ import pytest
from tools import getGuiItem, buildTestProject from tools import getGuiItem, buildTestProject
from PyQt5.QtWidgets import QAction, QDialog, QMessageBox from PyQt5.QtWidgets import QAction, QDialog, QMessageBox, QInputDialog
from novelwriter.enum import nwItemLayout, nwItemType from novelwriter.enum import nwItemLayout, nwItemType
from novelwriter.dialogs import GuiItemEditor from novelwriter.dialogs import GuiItemEditor
@@ -154,6 +154,7 @@ def testDlgItemEditor_Note(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
# Create Project and Open Document # Create Project and Open Document
buildTestProject(nwGUI, fncProj) buildTestProject(nwGUI, fncProj)
@@ -165,7 +166,7 @@ def testDlgItemEditor_Note(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
# Create Note # Create Note
nwGUI.treeView.projTree.clearSelection() nwGUI.treeView.projTree.clearSelection()
nwGUI.treeView.projTree._getTreeItem("000000000000a").setSelected(True) nwGUI.treeView.projTree._getTreeItem("000000000000a").setSelected(True)
nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None) nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None, isNote=True)
# Open Note # Open Note
assert nwGUI.openDocument("0000000000010") assert nwGUI.openDocument("0000000000010")
+5 -4
View File
@@ -26,7 +26,7 @@ from shutil import copyfile
from tools import cmpFiles, buildTestProject, XML_IGNORE, writeFile from tools import cmpFiles, buildTestProject, XML_IGNORE, writeFile
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMessageBox, QDialog from PyQt5.QtWidgets import QMessageBox, QDialog, QInputDialog
from novelwriter.gui import GuiDocEditor, GuiNovelTree, GuiOutline from novelwriter.gui import GuiDocEditor, GuiNovelTree, GuiOutline
from novelwriter.enum import nwItemType, nwWidget from novelwriter.enum import nwItemType, nwWidget
@@ -173,6 +173,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
monkeypatch.setattr(GuiItemEditor, "result", lambda *a: QDialog.Accepted) monkeypatch.setattr(GuiItemEditor, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True) monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True)
monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
# Create new, save, close project # Create new, save, close project
buildTestProject(nwGUI, fncProj) buildTestProject(nwGUI, fncProj)
@@ -241,7 +242,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
nwGUI.switchFocus(nwWidget.TREE) nwGUI.switchFocus(nwWidget.TREE)
nwGUI.treeView.projTree.clearSelection() nwGUI.treeView.projTree.clearSelection()
nwGUI.treeView.projTree._getTreeItem("000000000000a").setSelected(True) nwGUI.treeView.projTree._getTreeItem("000000000000a").setSelected(True)
nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None) nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None, isNote=True)
assert nwGUI.openSelectedItem() assert nwGUI.openSelectedItem()
# Type something into the document # Type something into the document
@@ -263,7 +264,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
nwGUI.switchFocus(nwWidget.TREE) nwGUI.switchFocus(nwWidget.TREE)
nwGUI.treeView.projTree.clearSelection() nwGUI.treeView.projTree.clearSelection()
nwGUI.treeView.projTree._getTreeItem("0000000000009").setSelected(True) nwGUI.treeView.projTree._getTreeItem("0000000000009").setSelected(True)
nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None) nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None, isNote=True)
assert nwGUI.openSelectedItem() assert nwGUI.openSelectedItem()
# Type something into the document # Type something into the document
@@ -285,7 +286,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
nwGUI.switchFocus(nwWidget.TREE) nwGUI.switchFocus(nwWidget.TREE)
nwGUI.treeView.projTree.clearSelection() nwGUI.treeView.projTree.clearSelection()
nwGUI.treeView.projTree._getTreeItem("000000000000b").setSelected(True) nwGUI.treeView.projTree._getTreeItem("000000000000b").setSelected(True)
nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None) nwGUI.treeView.projTree.newTreeItem(nwItemType.FILE, None, isNote=True)
assert nwGUI.openSelectedItem() assert nwGUI.openSelectedItem()
# Add Some Text # Add Some Text
+27 -13
View File
@@ -24,9 +24,8 @@ import os
from tools import buildTestProject from tools import buildTestProject
from PyQt5.QtWidgets import QAction, QMessageBox from PyQt5.QtWidgets import QAction, QMessageBox, QInputDialog
from novelwriter.guimain import GuiMain
from novelwriter.gui.projtree import GuiProjectTree from novelwriter.gui.projtree import GuiProjectTree
from novelwriter.enum import nwItemType, nwItemClass from novelwriter.enum import nwItemType, nwItemClass
@@ -40,7 +39,7 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiMain, "editItem", lambda *a: None) monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
nwTree = nwGUI.treeView nwTree = nwGUI.treeView
@@ -89,22 +88,31 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
assert nwGUI.theProject.tree["0000000000012"].itemRoot == "0000000000008" assert nwGUI.theProject.tree["0000000000012"].itemRoot == "0000000000008"
assert nwGUI.theProject.tree["0000000000012"].itemClass == nwItemClass.NOVEL assert nwGUI.theProject.tree["0000000000012"].itemClass == nwItemClass.NOVEL
# Add a new file next to the other new file # Add a new chapter next to the other new file
nwTree.setSelectedHandle("0000000000012") nwTree.setSelectedHandle("0000000000012")
assert nwTree.newTreeItem(nwItemType.FILE) is True assert nwTree.newTreeItem(nwItemType.FILE, hLevel=2) is True
assert nwGUI.theProject.tree["0000000000013"].itemParent == "0000000000011" assert nwGUI.theProject.tree["0000000000013"].itemParent == "0000000000011"
assert nwGUI.theProject.tree["0000000000013"].itemRoot == "0000000000008" assert nwGUI.theProject.tree["0000000000013"].itemRoot == "0000000000008"
assert nwGUI.theProject.tree["0000000000013"].itemClass == nwItemClass.NOVEL assert nwGUI.theProject.tree["0000000000013"].itemClass == nwItemClass.NOVEL
assert nwGUI.openDocument("0000000000013") assert nwGUI.openDocument("0000000000013")
assert nwGUI.docEditor.getText() == "## New Document\n\n" assert nwGUI.docEditor.getText() == "## New Chapter\n\n"
# Add a new scene next to the other new file
nwTree.setSelectedHandle("0000000000012")
assert nwTree.newTreeItem(nwItemType.FILE, hLevel=3) is True
assert nwGUI.theProject.tree["0000000000014"].itemParent == "0000000000011"
assert nwGUI.theProject.tree["0000000000014"].itemRoot == "0000000000008"
assert nwGUI.theProject.tree["0000000000014"].itemClass == nwItemClass.NOVEL
assert nwGUI.openDocument("0000000000014")
assert nwGUI.docEditor.getText() == "### New Scene\n\n"
# Add a new file to the characters folder # Add a new file to the characters folder
nwTree.setSelectedHandle("000000000000a") nwTree.setSelectedHandle("000000000000a")
assert nwTree.newTreeItem(nwItemType.FILE) is True assert nwTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True) is True
assert nwGUI.theProject.tree["0000000000014"].itemParent == "000000000000a" assert nwGUI.theProject.tree["0000000000015"].itemParent == "000000000000a"
assert nwGUI.theProject.tree["0000000000014"].itemRoot == "000000000000a" assert nwGUI.theProject.tree["0000000000015"].itemRoot == "000000000000a"
assert nwGUI.theProject.tree["0000000000014"].itemClass == nwItemClass.CHARACTER assert nwGUI.theProject.tree["0000000000015"].itemClass == nwItemClass.CHARACTER
assert nwGUI.openDocument("0000000000014") assert nwGUI.openDocument("0000000000015")
assert nwGUI.docEditor.getText() == "# New Note\n\n" assert nwGUI.docEditor.getText() == "# New Note\n\n"
# Make sure the sibling folder bug trap works # Make sure the sibling folder bug trap works
@@ -115,6 +123,12 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
assert "Internal error" in caplog.text assert "Internal error" in caplog.text
nwGUI.theProject.tree["0000000000013"].setParent("0000000000011") nwGUI.theProject.tree["0000000000013"].setParent("0000000000011")
# Cancel during creation
with monkeypatch.context() as mp:
mp.setattr(QInputDialog, "getText", lambda *a, **k: ("", False))
nwTree.setSelectedHandle("0000000000013")
assert nwTree.newTreeItem(nwItemType.FILE) is False
# Get the trash folder # Get the trash folder
nwTree.projTree._addTrashRoot() nwTree.projTree._addTrashRoot()
trashHandle = nwGUI.theProject.trashFolder() trashHandle = nwGUI.theProject.trashFolder()
@@ -148,7 +162,7 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiMain, "editItem", lambda *a: None) monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
nwTree = nwGUI.treeView nwTree = nwGUI.treeView
@@ -272,7 +286,7 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiMain, "editItem", lambda *a: None) monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
nwTree = nwGUI.treeView nwTree = nwGUI.treeView