diff --git a/novelwriter/custom.py b/novelwriter/custom.py
index d516e2dd..5d9d8122 100644
--- a/novelwriter/custom.py
+++ b/novelwriter/custom.py
@@ -421,6 +421,12 @@ class PagedDialog(QDialog):
self._buttonBox.addWidget(buttonBar)
return
+ def setCurrentWidget(self, widget):
+ """Forward the changing of tab to the QTabWidget.
+ """
+ self._tabBox.setCurrentWidget(widget)
+ return
+
# END Class PagedDialog
diff --git a/novelwriter/dialogs/projsettings.py b/novelwriter/dialogs/projsettings.py
index 86c268d6..eb96ffb2 100644
--- a/novelwriter/dialogs/projsettings.py
+++ b/novelwriter/dialogs/projsettings.py
@@ -43,7 +43,12 @@ logger = logging.getLogger(__name__)
class GuiProjectSettings(PagedDialog):
- def __init__(self, mainGui):
+ TAB_MAIN = 0
+ TAB_STATUS = 1
+ TAB_IMPORT = 2
+ TAB_REPLACE = 3
+
+ def __init__(self, mainGui, focusTab=TAB_MAIN):
super().__init__(parent=mainGui)
logger.debug("Initialising GuiProjectSettings ...")
@@ -83,12 +88,19 @@ class GuiProjectSettings(PagedDialog):
self.addControls(self.buttonBox)
# Flags
- self.spellChanged = False
+ self._spellChanged = False
+
+ # Focus Tab
+ self._focusTab(focusTab)
logger.debug("GuiProjectSettings initialisation complete")
return
+ @property
+ def spellChanged(self):
+ return self._spellChanged
+
##
# Slots
##
@@ -108,7 +120,7 @@ class GuiProjectSettings(PagedDialog):
self.theProject.setProjBackup(doBackup)
# Remember this as updating spell dictionary can be expensive
- self.spellChanged = self.theProject.setSpellLang(spellLang)
+ self._spellChanged = self.theProject.setSpellLang(spellLang)
if self.tabStatus.colChanged:
newList, delList = self.tabStatus.getNewList()
@@ -141,6 +153,19 @@ class GuiProjectSettings(PagedDialog):
# Internal Functions
##
+ def _focusTab(self, tab):
+ """Change which is the focused tab.
+ """
+ if tab == self.TAB_MAIN:
+ self.setCurrentWidget(self.tabMain)
+ elif tab == self.TAB_STATUS:
+ self.setCurrentWidget(self.tabStatus)
+ elif tab == self.TAB_IMPORT:
+ self.setCurrentWidget(self.tabImport)
+ elif tab == self.TAB_REPLACE:
+ self.setCurrentWidget(self.tabReplace)
+ return
+
def _saveGuiSettings(self):
"""Save GUI settings.
"""
diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py
index 96dc98f1..e34419d1 100644
--- a/novelwriter/gui/projtree.py
+++ b/novelwriter/gui/projtree.py
@@ -41,8 +41,8 @@ from PyQt5.QtWidgets import (
from novelwriter.core import DocMerger, DocSplitter
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert
-from novelwriter.dialogs import GuiDocMerge, GuiDocSplit, GuiEditLabel
-from novelwriter.constants import nwHeaders, trConst, nwLabels
+from novelwriter.dialogs import GuiDocMerge, GuiDocSplit, GuiEditLabel, GuiProjectSettings
+from novelwriter.constants import nwHeaders, nwUnicode, trConst, nwLabels
logger = logging.getLogger(__name__)
@@ -62,6 +62,9 @@ class GuiProjectView(QWidget):
selectedItemChanged = pyqtSignal(str)
openDocumentRequest = pyqtSignal(str, Enum, int, str)
+ # Requests for the main GUI
+ projectSettingsRequest = pyqtSignal(int)
+
def __init__(self, mainGui):
super().__init__(parent=mainGui)
@@ -102,9 +105,6 @@ class GuiProjectView(QWidget):
self.keyContext.activated.connect(lambda: self.projTree.openContextOnSelected())
# Function Mappings
- self.revealNewTreeItem = self.projTree.revealNewTreeItem
- self.renameTreeItem = self.projTree.renameTreeItem
- self.getTreeFromHandle = self.projTree.getTreeFromHandle
self.emptyTrash = self.projTree.emptyTrash
self.requestDeleteItem = self.projTree.requestDeleteItem
self.setTreeItemValues = self.projTree.setTreeItemValues
@@ -161,6 +161,16 @@ class GuiProjectView(QWidget):
"""
return self.projTree.hasFocus()
+ def renameTreeItem(self, tHandle=None):
+ """External request to rename an item or the currently selected
+ item. This is triggered by the global menu or keyboard shortcut.
+ """
+ if tHandle is None:
+ tHandle = self.projTree.getSelectedHandle()
+ if tHandle:
+ return self.projTree.renameTreeItem(tHandle)
+ return
+
##
# Public Slots
##
@@ -1111,10 +1121,12 @@ class GuiProjectTree(QTreeWidget):
open a context menu in-place.
"""
tItem = None
+ hasChild = False
selItem = self.itemAt(clickPos)
if isinstance(selItem, QTreeWidgetItem):
tHandle = selItem.data(self.C_NAME, Qt.UserRole)
tItem = self.theProject.tree[tHandle]
+ hasChild = selItem.childCount() > 0
if tItem is None:
logger.debug("No item found")
@@ -1128,9 +1140,8 @@ class GuiProjectTree(QTreeWidget):
trashHandle = self.theProject.tree.trashRoot()
if tItem.itemHandle == trashHandle and trashHandle is not None:
# The trash folder only has one option
- ctxMenu.addAction(
- self.tr("Empty Trash"), lambda: self.emptyTrash()
- )
+ aEmptyTrash = ctxMenu.addAction(self.tr("Empty Trash"))
+ aEmptyTrash.triggered.connect(lambda: self.emptyTrash())
ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
return True
@@ -1140,15 +1151,14 @@ class GuiProjectTree(QTreeWidget):
isRoot = tItem.isRootType()
isFolder = tItem.isFolderType()
isFile = tItem.isFileType()
- hasChild = selItem.childCount() > 0
if isFile:
- ctxMenu.addAction(
- self.tr("Open Document"),
+ aOpenDoc = ctxMenu.addAction(self.tr("Open Document"))
+ aOpenDoc.triggered.connect(
lambda: self.projView.openDocumentRequest.emit(tHandle, nwDocMode.EDIT, -1, "")
)
- ctxMenu.addAction(
- self.tr("View Document"),
+ aViewDoc = ctxMenu.addAction(self.tr("View Document"))
+ aViewDoc.triggered.connect(
lambda: self.projView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, -1, "")
)
ctxMenu.addSeparator()
@@ -1156,29 +1166,40 @@ class GuiProjectTree(QTreeWidget):
# Edit Item Settings
# ==================
- ctxMenu.addAction(
- self.tr("Change Label"), lambda: self.renameTreeItem(tHandle)
- )
+ aLabel = ctxMenu.addAction(self.tr("Change Label"))
+ aLabel.triggered.connect(lambda: self.renameTreeItem(tHandle))
if isFile:
- ctxMenu.addAction(
- self.tr("Toggle Active"), lambda: self._toggleItemActive(tHandle)
- )
+ aActive = ctxMenu.addAction(self.tr("Toggle Active"))
+ aActive.triggered.connect(lambda: self._toggleItemActive(tHandle))
+ checkMark = f" ({nwUnicode.U_CHECK})"
if tItem.isNovelLike():
mStatus = ctxMenu.addMenu(self.tr("Set Status to ..."))
for n, (key, entry) in enumerate(self.theProject.statusItems.items()):
- aStatus = mStatus.addAction(entry["icon"], entry["name"])
+ entryName = entry["name"] + (checkMark if tItem.itemStatus == key else "")
+ aStatus = mStatus.addAction(entry["icon"], entryName)
aStatus.triggered.connect(
lambda n, key=key: self._changeItemStatus(tHandle, key)
)
+ mStatus.addSeparator()
+ aManage1 = mStatus.addAction("Manage Labels ...")
+ aManage1.triggered.connect(
+ lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_STATUS)
+ )
else:
mImport = ctxMenu.addMenu(self.tr("Set Importance to ..."))
for n, (key, entry) in enumerate(self.theProject.importItems.items()):
- aImport = mImport.addAction(entry["icon"], entry["name"])
+ entryName = entry["name"] + (checkMark if tItem.itemImport == key else "")
+ aImport = mImport.addAction(entry["icon"], entryName)
aImport.triggered.connect(
lambda n, key=key: self._changeItemImport(tHandle, key)
)
+ mImport.addSeparator()
+ aManage2 = mImport.addAction("Manage Labels ...")
+ aManage2.triggered.connect(
+ lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_IMPORT)
+ )
# Transform Item
# ==============
@@ -1193,38 +1214,30 @@ class GuiProjectTree(QTreeWidget):
isNoteFile = isFile and tItem.isNoteLayout()
if (isNoteFile or isFolder) and tItem.documentAllowed():
- mTrans.addAction(
- self.tr("Convert to {0}").format(trDoc),
+ aConvert1 = mTrans.addAction(self.tr("Convert to {0}").format(trDoc))
+ aConvert1.triggered.connect(
lambda: self._changeItemLayout(tHandle, nwItemLayout.DOCUMENT)
)
if isDocFile or isFolder:
- mTrans.addAction(
- self.tr("Convert to {0}").format(trNote),
+ aConvert2 = mTrans.addAction(self.tr("Convert to {0}").format(trNote))
+ aConvert2.triggered.connect(
lambda: self._changeItemLayout(tHandle, nwItemLayout.NOTE)
)
if hasChild and isFile:
- mTrans.addAction(
- self.tr("Merge Child Items into Self"),
- lambda: self._mergeDocuments(tHandle, False)
- )
- mTrans.addAction(
- self.tr("Merge Child Items into New"),
- lambda: self._mergeDocuments(tHandle, True)
- )
+ aMerge1 = mTrans.addAction(self.tr("Merge Child Items into Self"))
+ aMerge1.triggered.connect(lambda: self._mergeDocuments(tHandle, False))
+ aMerge2 = mTrans.addAction(self.tr("Merge Child Items into New"))
+ aMerge2.triggered.connect(lambda: self._mergeDocuments(tHandle, True))
if hasChild and isFolder:
- mTrans.addAction(
- self.tr("Merge Documents in Folder"),
- lambda: self._mergeDocuments(tHandle, True)
- )
+ aMerge3 = mTrans.addAction(self.tr("Merge Documents in Folder"))
+ aMerge3.triggered.connect(lambda: self._mergeDocuments(tHandle, True))
if isFile:
- mTrans.addAction(
- self.tr("Split Document by Headers"),
- lambda: self._splitDocument(tHandle)
- )
+ aSplit1 = mTrans.addAction(self.tr("Split Document by Headers"))
+ aSplit1.triggered.connect(lambda: self._splitDocument(tHandle))
# Expand/Collapse/Delete
# ======================
@@ -1232,23 +1245,17 @@ class GuiProjectTree(QTreeWidget):
ctxMenu.addSeparator()
if hasChild:
- ctxMenu.addAction(
- self.tr("Expand All"),
- lambda: self.setExpandedFromHandle(tHandle, True)
- )
- ctxMenu.addAction(
- self.tr("Collapse All"),
- lambda: self.setExpandedFromHandle(tHandle, False)
- )
+ aExpand = ctxMenu.addAction(self.tr("Expand All"))
+ aExpand.triggered.connect(lambda: self.setExpandedFromHandle(tHandle, True))
+ aCollapse = ctxMenu.addAction(self.tr("Collapse All"))
+ aCollapse.triggered.connect(lambda: self.setExpandedFromHandle(tHandle, False))
if tItem.itemClass == nwItemClass.TRASH or isRoot or (isFolder and not hasChild):
- ctxMenu.addAction(
- self.tr("Delete Permanently"), lambda: self.permanentlyDeleteItem(tHandle)
- )
+ aDelete = ctxMenu.addAction(self.tr("Delete Permanently"))
+ aDelete.triggered.connect(lambda: self.permanentlyDeleteItem(tHandle))
else:
- ctxMenu.addAction(
- self.tr("Move to Trash"), lambda: self.moveItemToTrash(tHandle)
- )
+ aMoveTrash = ctxMenu.addAction(self.tr("Move to Trash"))
+ aMoveTrash.triggered.connect(lambda: self.moveItemToTrash(tHandle))
# Show Context Menu
ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index fee7c7d6..cf0a9dff 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -208,6 +208,7 @@ class GuiMain(QMainWindow):
self.projView.rootFolderChanged.connect(self.outlineView.updateRootItem)
self.projView.rootFolderChanged.connect(self.novelView.updateRootItem)
self.projView.rootFolderChanged.connect(self.projView.updateRootItem)
+ self.projView.projectSettingsRequest.connect(self.showProjectSettingsDialog)
self.novelView.selectedItemChanged.connect(self.itemDetails.updateViewBox)
self.novelView.openDocumentRequest.connect(self._openDocument)
@@ -806,15 +807,11 @@ class GuiMain(QMainWindow):
logger.error("No project open")
return False
- if tHandle is None:
- if self.docEditor.anyFocus() or self.isFocusMode:
- tHandle = self.docEditor.docHandle()
- else:
- tHandle = self.projView.getSelectedHandle()
- if tHandle:
- return self.projView.renameTreeItem(tHandle)
+ if tHandle is None and (self.docEditor.anyFocus() or self.isFocusMode):
+ tHandle = self.docEditor.docHandle()
+ self.projView.renameTreeItem(tHandle)
- return False
+ return True
def rebuildTrees(self):
"""Rebuild the project tree.
@@ -921,14 +918,15 @@ class GuiMain(QMainWindow):
return
- def showProjectSettingsDialog(self):
+ @pyqtSlot(int)
+ def showProjectSettingsDialog(self, focusTab=GuiProjectSettings.TAB_MAIN):
"""Open the project settings dialog.
"""
if not self.hasProject:
logger.error("No project open")
return False
- dlgProj = GuiProjectSettings(self)
+ dlgProj = GuiProjectSettings(self, focusTab=focusTab)
dlgProj.exec_()
if dlgProj.result() == QDialog.Accepted:
diff --git a/tests/reference/guiProjSettings_Dialog_nwProject.nwx b/tests/reference/guiProjSettings_Dialog_nwProject.nwx
deleted file mode 100644
index 307aae55..00000000
--- a/tests/reference/guiProjSettings_Dialog_nwProject.nwx
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
- Project Name
- Project Title
- Jane Doe
- John Doh
- 1
- 1
- 0
-
-
- True
- None
- False
- en
- None
- None
- None
- None
- 9
- 9
- 0
-
- B
- D
- With This Stuff
-
-
- %title%
- %title%
- %title%
- * * *
-
-
-
- New
- Note
- Finished
- Final
-
-
- New
- Minor
- Major
- Final
-
-
-
- -
-
- Novel
-
- -
-
- Title Page
-
- -
-
- New Chapter
-
- -
-
- New Chapter
-
- -
-
- New Scene
-
- -
-
- Plot
-
- -
-
- Characters
-
- -
-
- World
-
-
-
diff --git a/tests/test_dialogs/test_dlg_projsettings.py b/tests/test_dialogs/test_dlg_projsettings.py
index d194229c..48e896bf 100644
--- a/tests/test_dialogs/test_dlg_projsettings.py
+++ b/tests/test_dialogs/test_dlg_projsettings.py
@@ -19,56 +19,46 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
-from shutil import copyfile
-from tools import cmpFiles, getGuiItem, buildTestProject
+from novelwriter.enum import nwItemType
+from tools import C, getGuiItem, buildTestProject
from PyQt5.QtGui import QColor
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QAction, QMessageBox, QColorDialog
+from novelwriter.dialogs.editlabel import GuiEditLabel
from novelwriter.dialogs.projsettings import GuiProjectSettings
keyDelay = 2
typeDelay = 1
stepDelay = 20
-statusKeys = ["s000000", "s000001", "s000002", "s000003"]
-importKeys = ["i000004", "i000005", "i000006", "i000007"]
@pytest.mark.gui
-def testDlgProjSettings_Dialog(
- qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDir, refDir, mockRnd
-):
- """Test the full project settings dialog.
+def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
+ """Test the main dialog class. Saving settings is not tested in this
+ test, but are instead tested in the individual tab tests.
"""
- projFile = os.path.join(fncProj, "nwProject.nwx")
- testFile = os.path.join(outDir, "guiProjSettings_Dialog_nwProject.nwx")
- compFile = os.path.join(refDir, "guiProjSettings_Dialog_nwProject.nwx")
-
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
+ # Block the GUI blocking thread
+ monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *a: None)
+ monkeypatch.setattr(GuiProjectSettings, "result", lambda *a: QDialog.Accepted)
+ monkeypatch.setattr(GuiProjectSettings, "spellChanged", lambda *a: True)
+
# Check that we cannot open when there is no project
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
assert getGuiItem("GuiProjectSettings") is None
- # Create new project
- buildTestProject(nwGUI, fncProj)
- nwGUI.mainConf.backupPath = fncDir
-
+ # Pretend we have a project
+ nwGUI.hasProject = True
nwGUI.theProject.setSpellLang("en")
- nwGUI.theProject.setBookAuthors("Jane Smith\nJohn Smith")
- nwGUI.theProject.setAutoReplace({"A": "B", "C": "D"})
# Get the dialog object
- monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *a: None)
- monkeypatch.setattr(GuiProjectSettings, "result", lambda *a: QDialog.Accepted)
- monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
-
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000)
@@ -77,83 +67,189 @@ def testDlgProjSettings_Dialog(
projEdit.show()
qtbot.addWidget(projEdit)
+ # Switch Tabs
+ projEdit._focusTab(GuiProjectSettings.TAB_REPLACE)
+ assert projEdit._tabBox.currentWidget() == projEdit.tabReplace
+
+ projEdit._focusTab(GuiProjectSettings.TAB_IMPORT)
+ assert projEdit._tabBox.currentWidget() == projEdit.tabImport
+
+ projEdit._focusTab(GuiProjectSettings.TAB_STATUS)
+ assert projEdit._tabBox.currentWidget() == projEdit.tabStatus
+
+ projEdit._focusTab(GuiProjectSettings.TAB_MAIN)
+ assert projEdit._tabBox.currentWidget() == projEdit.tabMain
+
+ # Clean Up
+ projEdit._doClose()
+ # qtbot.stop()
+
+# END Test testDlgProjSettings_Dialog
+
+
+@pytest.mark.gui
+def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
+ """Test the main tab of the project settings dialog.
+ """
+ # Block message box
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
+
+ # Mock components
+ monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
+
+ # Create new project
+ buildTestProject(nwGUI, fncProj)
+ mockRnd.reset()
+ nwGUI.mainConf.backupPath = fncDir
+
+ # Set some values
+ theProject = nwGUI.theProject
+ theProject.setSpellLang("en")
+ theProject.setBookAuthors("Jane Smith\nJohn Smith")
+ theProject.setAutoReplace({"A": "B", "C": "D"})
+
+ # Create Dialog
+ projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_MAIN)
+ projSettings.show()
+ qtbot.addWidget(projSettings)
+
# Settings Tab
# ============
- assert projEdit.tabMain.editName.text() == "New Project"
- assert projEdit.tabMain.editTitle.text() == "New Novel"
- assert projEdit.tabMain.editAuthors.toPlainText() == "Jane Smith\nJohn Smith"
- assert projEdit.tabMain.spellLang.currentData() == "en"
- assert projEdit.tabMain.doBackup.isChecked() is False
+ tabMain = projSettings.tabMain
+
+ assert tabMain.editName.text() == "New Project"
+ assert tabMain.editTitle.text() == "New Novel"
+ assert tabMain.editAuthors.toPlainText() == "Jane Smith\nJohn Smith"
+ assert tabMain.spellLang.currentData() == "en"
+ assert tabMain.doBackup.isChecked() is False
qtbot.wait(stepDelay)
- projEdit.tabMain.editName.setText("")
+ tabMain.editName.setText("")
for c in "Project Name":
- qtbot.keyClick(projEdit.tabMain.editName, c, delay=typeDelay)
- projEdit.tabMain.editTitle.setText("")
+ qtbot.keyClick(tabMain.editName, c, delay=typeDelay)
+ tabMain.editTitle.setText("")
for c in "Project Title":
- qtbot.keyClick(projEdit.tabMain.editTitle, c, delay=typeDelay)
+ qtbot.keyClick(tabMain.editTitle, c, delay=typeDelay)
- projEdit.tabMain.editAuthors.clear()
+ tabMain.editAuthors.clear()
for c in "Jane Doe":
- qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=typeDelay)
- qtbot.keyClick(projEdit.tabMain.editAuthors, Qt.Key_Return, delay=keyDelay)
+ qtbot.keyClick(tabMain.editAuthors, c, delay=typeDelay)
+ qtbot.keyClick(tabMain.editAuthors, Qt.Key_Return, delay=keyDelay)
for c in "John Doh":
- qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=typeDelay)
- qtbot.keyClick(projEdit.tabMain.editAuthors, Qt.Key_Return, delay=keyDelay)
+ qtbot.keyClick(tabMain.editAuthors, c, delay=typeDelay)
+ qtbot.keyClick(tabMain.editAuthors, Qt.Key_Return, delay=keyDelay)
qtbot.wait(stepDelay)
- assert projEdit.tabMain.editName.text() == "Project Name"
- assert projEdit.tabMain.editTitle.text() == "Project Title"
- assert projEdit.tabMain.editAuthors.toPlainText() == "Jane Doe\nJohn Doh\n"
+ assert tabMain.editName.text() == "Project Name"
+ assert tabMain.editTitle.text() == "Project Title"
+ assert tabMain.editAuthors.toPlainText() == "Jane Doe\nJohn Doh\n"
+ assert projSettings.spellChanged is False
+
+ projSettings._doSave()
+ assert theProject.projName == "Project Name"
+ assert theProject.bookTitle == "Project Title"
+ assert theProject.bookAuthors == ["Jane Doe", "John Doh"]
+
+ # Clean up
+ projSettings._doClose()
+ # qtbot.stop()
+
+# END Test testDlgProjSettings_Main
+
+
+@pytest.mark.gui
+def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
+ """Test the status and importance tabs of the project settings
+ dialog.
+ """
+ # Block message box
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
+
+ # Mock components
+ monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
+
+ # Create new project
+ mockRnd.reset()
+ buildTestProject(nwGUI, fncProj)
+ nwGUI.mainConf.backupPath = fncDir
+
+ # Set some values
+ theProject = nwGUI.theProject
+ theProject.tree[C.hTitlePage].setStatus(C.sFinished)
+ theProject.tree[C.hChapterDoc].setStatus(C.sDraft)
+ theProject.tree[C.hSceneDoc].setStatus(C.sDraft)
+
+ nwGUI.projView.projTree.setSelectedHandle(C.hPlotRoot)
+ nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
+ nwGUI.projView.projTree.setSelectedHandle(C.hCharRoot)
+ nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
+ nwGUI.projView.projTree.setSelectedHandle(C.hWorldRoot)
+ nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
+
+ hPlotNote = "0000000000010"
+ hCharNote = "0000000000011"
+ hWorldNote = "0000000000012"
+
+ theProject.tree[hPlotNote].setImport(C.iMajor)
+ theProject.tree[hCharNote].setImport(C.iMajor)
+ theProject.tree[hWorldNote].setImport(C.iMain)
+
+ # Create Dialog
+ projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_STATUS)
+ projSettings.show()
+ qtbot.addWidget(projSettings)
# Status Tab
# ==========
- projEdit._tabBox.setCurrentWidget(projEdit.tabStatus)
+ tabStatus = projSettings.tabStatus
- assert projEdit.tabStatus.colChanged is False
- assert projEdit.tabStatus.getNewList() == ([], [])
- assert projEdit.tabStatus.listBox.topLevelItemCount() == 4
+ assert tabStatus.colChanged is False
+ assert tabStatus.getNewList() == ([], [])
+ assert tabStatus.listBox.topLevelItemCount() == 4
# Can't delete the first item (it's in use)
- projEdit.tabStatus.listBox.clearSelection()
- projEdit.tabStatus.listBox.topLevelItem(0).setSelected(True)
- qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton)
- assert projEdit.tabStatus.listBox.topLevelItemCount() == 4
+ tabStatus.listBox.clearSelection()
+ tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(0))
+ qtbot.mouseClick(tabStatus.delButton, Qt.LeftButton)
+ assert tabStatus.listBox.topLevelItemCount() == 4
- # Can delete the third item
- projEdit.tabStatus.listBox.clearSelection()
- projEdit.tabStatus.listBox.topLevelItem(2).setSelected(True)
- qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton)
- assert projEdit.tabStatus.listBox.topLevelItemCount() == 3
+ # Can delete the second item
+ tabStatus.listBox.clearSelection()
+ tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(1))
+ qtbot.mouseClick(tabStatus.delButton, Qt.LeftButton)
+ assert tabStatus.listBox.topLevelItemCount() == 3
# Add a new item
- monkeypatch.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
- qtbot.mouseClick(projEdit.tabStatus.addButton, Qt.LeftButton)
- projEdit.tabStatus.listBox.topLevelItem(3).setSelected(True)
- for n in range(8):
- qtbot.keyClick(projEdit.tabStatus.editName, Qt.Key_Backspace, delay=typeDelay)
- for c in "Final":
- qtbot.keyClick(projEdit.tabStatus.editName, c, delay=typeDelay)
- qtbot.mouseClick(projEdit.tabStatus.colButton, Qt.LeftButton)
- qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton)
- assert projEdit.tabStatus.listBox.topLevelItemCount() == 4
- qtbot.wait(stepDelay)
+ with monkeypatch.context() as mp:
+ mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
+ qtbot.mouseClick(tabStatus.addButton, Qt.LeftButton)
+ tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(3))
+ for _ in range(8):
+ qtbot.keyClick(tabStatus.editName, Qt.Key_Backspace, delay=typeDelay)
+ for c in "Final":
+ qtbot.keyClick(tabStatus.editName, c, delay=typeDelay)
+ qtbot.mouseClick(tabStatus.colButton, Qt.LeftButton)
+ qtbot.mouseClick(tabStatus.saveButton, Qt.LeftButton)
+ assert tabStatus.listBox.topLevelItemCount() == 4
- assert projEdit.tabStatus.colChanged is True
- assert projEdit.tabStatus.getNewList() == (
+ assert tabStatus.colChanged is True
+ assert tabStatus.getNewList() == (
[
{
- "key": statusKeys[0],
+ "key": C.sNew,
"name": "New",
"cols": (100, 100, 100)
}, {
- "key": statusKeys[1],
- "name": "Note",
- "cols": (200, 50, 0)
+ "key": C.sDraft,
+ "name": "Draft",
+ "cols": (200, 150, 0)
}, {
- "key": statusKeys[3],
+ "key": C.sFinished,
"name": "Finished",
"cols": (50, 200, 0)
}, {
@@ -162,121 +258,201 @@ def testDlgProjSettings_Dialog(
"cols": (20, 30, 40)
}
], [
- statusKeys[2] # Deleted item
+ C.sNote # Deleted item
]
)
- # Move items
- projEdit.tabStatus.listBox.clearSelection()
- projEdit.tabStatus._moveItem(1)
- assert [x["key"] for x in projEdit.tabStatus.getNewList()[0]] == [
- statusKeys[0], statusKeys[1], statusKeys[3], None
+ # Move items, none selected -> no change
+ tabStatus.listBox.clearSelection()
+ tabStatus._moveItem(1)
+ assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ C.sNew, C.sDraft, C.sFinished, None
]
- projEdit.tabStatus.listBox.clearSelection()
- projEdit.tabStatus.listBox.topLevelItem(0).setSelected(True)
- projEdit.tabStatus._moveItem(-1)
- assert [x["key"] for x in projEdit.tabStatus.getNewList()[0]] == [
- statusKeys[0], statusKeys[1], statusKeys[3], None
+ # Move items, first selected, move up -> no change
+ tabStatus.listBox.clearSelection()
+ tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(0))
+ tabStatus._moveItem(-1)
+ assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ C.sNew, C.sDraft, C.sFinished, None
]
- projEdit.tabStatus.listBox.clearSelection()
- projEdit.tabStatus.listBox.topLevelItem(3).setSelected(True)
- projEdit.tabStatus._moveItem(-1)
- assert [x["key"] for x in projEdit.tabStatus.getNewList()[0]] == [
- statusKeys[0], statusKeys[1], None, statusKeys[3]
+ # Move items, last selected, move up -> allowed
+ tabStatus.listBox.clearSelection()
+ tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(3))
+ tabStatus._moveItem(-1)
+ assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ C.sNew, C.sDraft, None, C.sFinished
]
- projEdit.tabStatus._moveItem(1)
- assert [x["key"] for x in projEdit.tabStatus.getNewList()[0]] == [
- statusKeys[0], statusKeys[1], statusKeys[3], None
+
+ # Move items, same selected, move down -> allowed
+ tabStatus._moveItem(1)
+ assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ C.sNew, C.sDraft, C.sFinished, None
]
# Importance Tab
# ==============
- projEdit._tabBox.setCurrentWidget(projEdit.tabImport)
- projEdit.tabStatus.listBox.clearSelection()
- projEdit.tabImport.listBox.topLevelItem(3).setSelected(True)
- qtbot.mouseClick(projEdit.tabImport.delButton, Qt.LeftButton)
- qtbot.mouseClick(projEdit.tabImport.addButton, Qt.LeftButton)
- projEdit.tabStatus.listBox.clearSelection()
- projEdit.tabImport.listBox.topLevelItem(3).setSelected(True)
- for n in range(8):
- qtbot.keyClick(projEdit.tabImport.editName, Qt.Key_Backspace, delay=typeDelay)
- for c in "Final":
- qtbot.keyClick(projEdit.tabImport.editName, c, delay=typeDelay)
- qtbot.mouseClick(projEdit.tabImport.saveButton, Qt.LeftButton)
- qtbot.wait(stepDelay)
+ tabImport = projSettings.tabImport
+ projSettings._focusTab(GuiProjectSettings.TAB_IMPORT)
+
+ # Delete unused entry
+ tabImport.listBox.clearSelection()
+ tabImport.listBox.setCurrentItem(tabImport.listBox.topLevelItem(1))
+ qtbot.mouseClick(tabImport.delButton, Qt.LeftButton)
+ assert tabImport.listBox.topLevelItemCount() == 3
+
+ # Add a new entry
+ with monkeypatch.context() as mp:
+ mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
+ qtbot.mouseClick(tabImport.addButton, Qt.LeftButton)
+ tabImport.listBox.clearSelection()
+ tabImport.listBox.setCurrentItem(tabImport.listBox.topLevelItem(3))
+ for _ in range(8):
+ qtbot.keyClick(tabImport.editName, Qt.Key_Backspace, delay=typeDelay)
+ for c in "Final":
+ qtbot.keyClick(tabImport.editName, c, delay=typeDelay)
+ qtbot.mouseClick(tabImport.colButton, Qt.LeftButton)
+ qtbot.mouseClick(tabImport.saveButton, Qt.LeftButton)
+ assert tabImport.listBox.topLevelItemCount() == 4
+
+ assert tabImport.colChanged is True
+ assert tabImport.getNewList() == (
+ [
+ {
+ "key": C.iNew,
+ "name": "New",
+ "cols": (100, 100, 100)
+ }, {
+ "key": C.iMajor,
+ "name": "Major",
+ "cols": (200, 150, 0)
+ }, {
+ "key": C.iMain,
+ "name": "Main",
+ "cols": (50, 200, 0)
+ }, {
+ "key": None,
+ "name": "Final",
+ "cols": (20, 30, 40)
+ }
+ ], [
+ C.iMinor # Deleted item
+ ]
+ )
+
+ # Check Project
+ projSettings._doSave()
+
+ statusItems = dict(theProject.statusItems.items())
+ assert statusItems[C.sNew]["name"] == "New"
+ assert statusItems[C.sDraft]["name"] == "Draft"
+ assert statusItems[C.sFinished]["name"] == "Finished"
+ assert statusItems["s000013"]["name"] == "Final"
+
+ importItems = dict(theProject.importItems.items())
+ assert importItems[C.iNew]["name"] == "New"
+ assert importItems[C.iMajor]["name"] == "Major"
+ assert importItems[C.iMain]["name"] == "Main"
+ assert importItems["i000014"]["name"] == "Final"
+
+ # Clean up
+ # qtbot.stop()
+ projSettings._doClose()
+
+# END Test testDlgProjSettings_StatusImport
+
+
+@pytest.mark.gui
+def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
+ """Test the auto-replace tab of the project settings dialog.
+ """
+ # Block message box
+ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes)
+ monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
+
+ # Mock components
+ monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
+
+ # Create new project
+ mockRnd.reset()
+ buildTestProject(nwGUI, fncProj)
+ nwGUI.mainConf.backupPath = fncDir
+
+ # Set some values
+ theProject = nwGUI.theProject
+ theProject.autoReplace = {
+ "A": "B", "C": "D"
+ }
+
+ # Create Dialog
+ projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_REPLACE)
+ projSettings.show()
+ qtbot.addWidget(projSettings)
# Auto-Replace Tab
# ================
- qtbot.wait(stepDelay)
- projEdit._tabBox.setCurrentWidget(projEdit.tabReplace)
+ tabReplace = projSettings.tabReplace
- assert projEdit.tabReplace.listBox.topLevelItem(0).text(0) == ""
- assert projEdit.tabReplace.listBox.topLevelItem(0).text(1) == "B"
- assert projEdit.tabReplace.listBox.topLevelItem(1).text(0) == ""
- assert projEdit.tabReplace.listBox.topLevelItem(1).text(1) == "D"
+ assert tabReplace.listBox.topLevelItem(0).text(0) == ""
+ assert tabReplace.listBox.topLevelItem(0).text(1) == "B"
+ assert tabReplace.listBox.topLevelItem(1).text(0) == ""
+ assert tabReplace.listBox.topLevelItem(1).text(1) == "D"
+ assert tabReplace.listBox.topLevelItemCount() == 2
- qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
- projEdit.tabReplace.listBox.topLevelItem(2).setSelected(True)
- projEdit.tabReplace.editKey.setText("")
+ # Nothing to save or delete
+ tabReplace.listBox.clearSelection()
+ assert tabReplace._saveEntry() is False
+ assert tabReplace._delEntry() is False
+ assert tabReplace.listBox.topLevelItemCount() == 2
+
+ # Create a new entry
+ qtbot.mouseClick(tabReplace.addButton, Qt.LeftButton)
+ assert tabReplace.listBox.topLevelItemCount() == 3
+ assert tabReplace.listBox.topLevelItem(2).text(0) == ""
+ assert tabReplace.listBox.topLevelItem(2).text(1) == ""
+
+ # Edit the entry
+ tabReplace.listBox.setCurrentItem(tabReplace.listBox.topLevelItem(2))
+ tabReplace.editKey.setText("")
for c in "Th is ":
- qtbot.keyClick(projEdit.tabReplace.editKey, c, delay=typeDelay)
- projEdit.tabReplace.editValue.setText("")
+ qtbot.keyClick(tabReplace.editKey, c, delay=typeDelay)
+ tabReplace.editValue.setText("")
for c in "With This Stuff ":
- qtbot.keyClick(projEdit.tabReplace.editValue, c, delay=typeDelay)
- qtbot.mouseClick(projEdit.tabReplace.saveButton, Qt.LeftButton)
+ qtbot.keyClick(tabReplace.editValue, c, delay=typeDelay)
+ qtbot.mouseClick(tabReplace.saveButton, Qt.LeftButton)
+ assert tabReplace.listBox.topLevelItem(2).text(0) == ""
+ assert tabReplace.listBox.topLevelItem(2).text(1) == "With This Stuff "
- qtbot.wait(stepDelay)
- projEdit.tabReplace.listBox.clearSelection()
- assert not projEdit.tabReplace._saveEntry()
- assert not projEdit.tabReplace._delEntry()
- qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
+ # Create a new entry again
+ tabReplace.listBox.clearSelection()
+ qtbot.mouseClick(tabReplace.addButton, Qt.LeftButton)
+ assert tabReplace.listBox.topLevelItemCount() == 4
+ # The list is sorted, so we must find it
newIdx = -1
- for i in range(projEdit.tabReplace.listBox.topLevelItemCount()):
- if projEdit.tabReplace.listBox.topLevelItem(i).text(0) == "":
+ for i in range(tabReplace.listBox.topLevelItemCount()):
+ if tabReplace.listBox.topLevelItem(i).text(0) == "":
newIdx = i
break
-
assert newIdx >= 0
- newItem = projEdit.tabReplace.listBox.topLevelItem(newIdx)
- projEdit.tabReplace.listBox.setCurrentItem(newItem)
- qtbot.mouseClick(projEdit.tabReplace.delButton, Qt.LeftButton)
- qtbot.wait(stepDelay)
- # Save & Check
- # ============
+ # Then delete the new item
+ tabReplace.listBox.setCurrentItem(tabReplace.listBox.topLevelItem(newIdx))
+ qtbot.mouseClick(tabReplace.delButton, Qt.LeftButton)
+ assert tabReplace.listBox.topLevelItemCount() == 3
- projEdit._doSave()
+ # Check Project
+ projSettings._doSave()
+ assert theProject.autoReplace == {
+ "A": "B", "C": "D", "This": "With This Stuff"
+ }
- # Open again, and check project settings
- nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
- qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000)
+ # Clean up
+ # qtbot.stop()
+ projSettings._doClose()
- projEdit = getGuiItem("GuiProjectSettings")
- assert isinstance(projEdit, GuiProjectSettings)
-
- qtbot.addWidget(projEdit)
- assert projEdit.tabMain.editName.text() == "Project Name"
- assert projEdit.tabMain.editTitle.text() == "Project Title"
- theAuth = projEdit.tabMain.editAuthors.toPlainText().strip().splitlines()
- assert len(theAuth) == 2
- assert theAuth[0] == "Jane Doe"
- assert theAuth[1] == "John Doh"
-
- projEdit._doClose()
- qtbot.wait(stepDelay)
-
- assert nwGUI.saveProject()
- qtbot.wait(stepDelay)
-
- # Check the files
- copyfile(projFile, testFile)
- assert cmpFiles(testFile, compFile, [2, 8, 9, 10])
-
- # qtbot.stopForInteraction()
-
-# END Test testDlgProjSettings_Dialog
+# END Test testDlgProjSettings_Replace
diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py
index b3bc49b1..68f02c71 100644
--- a/tests/test_gui/test_gui_doceditor.py
+++ b/tests/test_gui/test_gui_doceditor.py
@@ -1144,7 +1144,7 @@ def testGuiEditor_Tags(qtbot, monkeypatch, nwGUI, nwMinimal, ipsumText):
assert nwGUI.openDocument(cHandle) is True
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.saveDocument() is True
- assert nwGUI.projView.revealNewTreeItem(cHandle)
+ assert nwGUI.projView.projTree.revealNewTreeItem(cHandle)
nwGUI.docEditor.updateTagHighLighting()
# Follow Tag
diff --git a/tests/test_gui/test_gui_outline.py b/tests/test_gui/test_gui_outline.py
index 2f33cf7a..457be313 100644
--- a/tests/test_gui/test_gui_outline.py
+++ b/tests/test_gui/test_gui_outline.py
@@ -183,7 +183,7 @@ def testGuiOutline_Content(qtbot, monkeypatch, nwGUI, nwLipsum):
# Add a second novel folder
newHandle = nwGUI.theProject.newRoot(nwItemClass.NOVEL)
- nwGUI.projView.revealNewTreeItem(newHandle)
+ nwGUI.projView.projTree.revealNewTreeItem(newHandle)
# Check new values in dropdown list
assert outlineBar.novelValue.itemData(0) == lipHandle
@@ -202,7 +202,7 @@ def testGuiOutline_Content(qtbot, monkeypatch, nwGUI, nwLipsum):
aHandle = nwGUI.theProject.newFile(dTitle, newHandle)
hHash = "#"*hLevel
writeFile(os.path.join(nwLipsum, "content", f"{aHandle}.nwd"), f"{hHash} {dTitle}\n\n")
- nwGUI.projView.revealNewTreeItem(aHandle)
+ nwGUI.projView.projTree.revealNewTreeItem(aHandle)
nwGUI.rebuildIndex()
diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py
index b5201846..ecf78341 100644
--- a/tests/test_gui/test_gui_projtree.py
+++ b/tests/test_gui/test_gui_projtree.py
@@ -160,11 +160,11 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
# ============
# Also check error handling in reveal function
- assert projView.revealNewTreeItem("abc") is False
+ assert projView.projTree.revealNewTreeItem("abc") is False
# Add an item that cannot be displayed in the tree
nHandle = theProject.newFile("Test", None)
- assert projView.revealNewTreeItem(nHandle) is False
+ assert projView.projTree.revealNewTreeItem(nHandle) is False
# Clean up
# qtbot.stop()
@@ -184,10 +184,11 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
- nwTree = nwGUI.projView
+ projView = nwGUI.projView
+ projTree = nwGUI.projView.projTree
# Try to move item with no project
- assert nwTree.projTree.moveTreeItem(1) is False
+ assert projView.projTree.moveTreeItem(1) is False
# Create a project
prjDir = os.path.join(fncDir, "project")
@@ -197,68 +198,68 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
# ==============
# Add some files
- nwTree.setSelectedHandle(C.hChapterDir)
- assert nwTree.projTree.newTreeItem(nwItemType.FILE) is True
- assert nwTree.projTree.newTreeItem(nwItemType.FILE) is True
- assert nwTree.projTree.newTreeItem(nwItemType.FILE) is True
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ projView.setSelectedHandle(C.hChapterDir)
+ assert projTree.newTreeItem(nwItemType.FILE) is True
+ assert projTree.newTreeItem(nwItemType.FILE) is True
+ assert projTree.newTreeItem(nwItemType.FILE) is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000011", "0000000000012",
]
# Move with no selections
- nwTree.projTree.clearSelection()
- assert nwTree.projTree.moveTreeItem(1) is False
+ projTree.clearSelection()
+ assert projTree.moveTreeItem(1) is False
# Move second item up twice (should give same result)
- nwTree.setSelectedHandle(C.hSceneDoc)
- assert nwTree.projTree.moveTreeItem(-1) is True
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ projView.setSelectedHandle(C.hSceneDoc)
+ assert projTree.moveTreeItem(-1) is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hSceneDoc, C.hChapterDoc,
"0000000000010", "0000000000011", "0000000000012",
]
- assert nwTree.projTree.moveTreeItem(-1) is False
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ assert projTree.moveTreeItem(-1) is False
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hSceneDoc, C.hChapterDoc,
"0000000000010", "0000000000011", "0000000000012",
]
# Restore
- assert nwTree.projTree.moveTreeItem(1) is True
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ assert projTree.moveTreeItem(1) is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000011", "0000000000012",
]
# Move fifth item down twice (should give same result)
- nwTree.setSelectedHandle("0000000000011")
- assert nwTree.projTree.moveTreeItem(1) is True
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ projView.setSelectedHandle("0000000000011")
+ assert projTree.moveTreeItem(1) is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000012", "0000000000011",
]
- assert nwTree.projTree.moveTreeItem(1) is False
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ assert projTree.moveTreeItem(1) is False
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000012", "0000000000011",
]
# Restore
- assert nwTree.projTree.moveTreeItem(-1) is True
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ assert projTree.moveTreeItem(-1) is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000011", "0000000000012",
]
# Move down again, and restore via undo
- nwTree.setSelectedHandle("0000000000011")
- assert nwTree.projTree.moveTreeItem(1) is True
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ projView.setSelectedHandle("0000000000011")
+ assert projTree.moveTreeItem(1) is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000012", "0000000000011",
]
- assert nwTree.projTree.undoLastMove() is True
- assert nwTree.getTreeFromHandle(C.hChapterDir) == [
+ assert projTree.undoLastMove() is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000011", "0000000000012",
]
@@ -266,19 +267,19 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
# Root Folder
# ===========
- nwTree.setSelectedHandle(C.hNovelRoot)
+ projView.setSelectedHandle(C.hNovelRoot)
assert nwGUI.theProject.tree._treeOrder.index(C.hNovelRoot) == 0
# Move novel folder up
- assert nwTree.projTree.moveTreeItem(-1) is False
+ assert projTree.moveTreeItem(-1) is False
assert nwGUI.theProject.tree._treeOrder.index(C.hNovelRoot) == 0
# Move novel folder down
- assert nwTree.projTree.moveTreeItem(1) is True
+ assert projTree.moveTreeItem(1) is True
assert nwGUI.theProject.tree._treeOrder.index(C.hNovelRoot) == 1
# Move novel folder up again
- assert nwTree.projTree.moveTreeItem(-1) is True
+ assert projTree.moveTreeItem(-1) is True
assert nwGUI.theProject.tree._treeOrder.index(C.hNovelRoot) == 0
# Clean up
@@ -299,76 +300,77 @@ def testGuiProjTree_RequestDeleteItem(qtbot, caplog, monkeypatch, nwGUI, fncDir,
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
- nwView = nwGUI.projView
+ projView = nwGUI.projView
+ projTree = nwGUI.projView.projTree
# Try to run with no project
- assert nwView.requestDeleteItem() is False
+ assert projView.requestDeleteItem() is False
# Create a project
prjDir = os.path.join(fncDir, "project")
buildTestProject(nwGUI, prjDir)
# Try emptying the trash already now, when there is no trash folder
- assert nwView.emptyTrash() is False
+ assert projView.emptyTrash() is False
# Add some files
- nwView.setSelectedHandle(C.hChapterDir)
- assert nwView.projTree.newTreeItem(nwItemType.FILE) is True
- assert nwView.projTree.newTreeItem(nwItemType.FILE) is True
- assert nwView.projTree.newTreeItem(nwItemType.FILE) is True
- assert nwView.getTreeFromHandle(C.hChapterDir) == [
+ projView.setSelectedHandle(C.hChapterDir)
+ assert projTree.newTreeItem(nwItemType.FILE) is True
+ assert projTree.newTreeItem(nwItemType.FILE) is True
+ assert projTree.newTreeItem(nwItemType.FILE) is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010", "0000000000011", "0000000000012",
]
# Delete item without focus -> blocked
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: False)
- nwView.setSelectedHandle("0000000000012")
- assert nwView.requestDeleteItem() is False
+ projView.setSelectedHandle("0000000000012")
+ assert projView.requestDeleteItem() is False
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
# No selection made
- nwView.projTree.clearSelection()
+ projTree.clearSelection()
caplog.clear()
- assert nwView.requestDeleteItem() is False
+ assert projView.requestDeleteItem() is False
assert "no item to delete" in caplog.text
# Not a valid handle
- nwView.projTree.clearSelection()
+ projTree.clearSelection()
caplog.clear()
- assert nwView.requestDeleteItem("0000000000000") is False
+ assert projView.requestDeleteItem("0000000000000") is False
assert "No tree item with handle '0000000000000'" in caplog.text
# Delete Root Folders
# ===================
- assert nwView.requestDeleteItem(C.hNovelRoot) is False # Novel Root is blocked
- assert nwView.requestDeleteItem(C.hCharRoot) is True # Character Root
+ assert projView.requestDeleteItem(C.hNovelRoot) is False # Novel Root is blocked
+ assert projView.requestDeleteItem(C.hCharRoot) is True # Character Root
# Delete File
# ===========
# Block adding trash folder
- funcPointer = nwView.projTree._addTrashRoot
- nwView.projTree._addTrashRoot = lambda *a: None
- assert nwView.requestDeleteItem("0000000000012") is False
- nwView.projTree._addTrashRoot = funcPointer
+ funcPointer = projTree._addTrashRoot
+ projTree._addTrashRoot = lambda *a: None
+ assert projView.requestDeleteItem("0000000000012") is False
+ projTree._addTrashRoot = funcPointer
# Delete last two documents, which also adds the trash folder
- assert nwView.requestDeleteItem("0000000000012") is True
- assert nwView.requestDeleteItem("0000000000011") is True
- assert nwView.getTreeFromHandle(C.hChapterDir) == [
+ assert projView.requestDeleteItem("0000000000012") is True
+ assert projView.requestDeleteItem("0000000000011") is True
+ assert projTree.getTreeFromHandle(C.hChapterDir) == [
C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010"
]
trashHandle = nwGUI.theProject.tree.trashRoot()
- assert nwView.getTreeFromHandle(trashHandle) == [
+ assert projTree.getTreeFromHandle(trashHandle) == [
trashHandle, "0000000000012", "0000000000011"
]
# Try to delete the trash folder
caplog.clear()
- assert nwView.requestDeleteItem("0000000000013") is False
+ assert projView.requestDeleteItem("0000000000013") is False
assert "Cannot delete the Trash folder" in caplog.text
nwGUI.closeProject()
diff --git a/tests/test_gui/test_gui_statusbar.py b/tests/test_gui/test_gui_statusbar.py
index 6c99642f..e2e9a5bb 100644
--- a/tests/test_gui/test_gui_statusbar.py
+++ b/tests/test_gui/test_gui_statusbar.py
@@ -40,7 +40,7 @@ def testGuiStatusBar_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
cHandle = nwGUI.theProject.newFile("A Note", C.hCharRoot)
newDoc = NWDoc(nwGUI.theProject, cHandle)
newDoc.writeDocument("# A Note\n\n")
- nwGUI.projView.revealNewTreeItem(cHandle)
+ nwGUI.projView.projTree.revealNewTreeItem(cHandle)
nwGUI.rebuildIndex(beQuiet=True)
# Reference Time
diff --git a/tests/tools.py b/tests/tools.py
index 4744d472..4a97c930 100644
--- a/tests/tools.py
+++ b/tests/tools.py
@@ -30,6 +30,17 @@ XML_IGNORE = ("