Replace the item editor with the label editor dialog
This commit is contained in:
@@ -22,7 +22,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
from novelwriter.dialogs.about import GuiAbout
|
from novelwriter.dialogs.about import GuiAbout
|
||||||
from novelwriter.dialogs.docmerge import GuiDocMerge
|
from novelwriter.dialogs.docmerge import GuiDocMerge
|
||||||
from novelwriter.dialogs.docsplit import GuiDocSplit
|
from novelwriter.dialogs.docsplit import GuiDocSplit
|
||||||
from novelwriter.dialogs.itemeditor import GuiItemEditor
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
from novelwriter.dialogs.preferences import GuiPreferences
|
from novelwriter.dialogs.preferences import GuiPreferences
|
||||||
from novelwriter.dialogs.projdetails import GuiProjectDetails
|
from novelwriter.dialogs.projdetails import GuiProjectDetails
|
||||||
from novelwriter.dialogs.projload import GuiProjectLoad
|
from novelwriter.dialogs.projload import GuiProjectLoad
|
||||||
@@ -35,7 +35,7 @@ __all__ = [
|
|||||||
"GuiAbout",
|
"GuiAbout",
|
||||||
"GuiDocMerge",
|
"GuiDocMerge",
|
||||||
"GuiDocSplit",
|
"GuiDocSplit",
|
||||||
"GuiItemEditor",
|
"GuiEditLabel",
|
||||||
"GuiPreferences",
|
"GuiPreferences",
|
||||||
"GuiProjectDetails",
|
"GuiProjectDetails",
|
||||||
"GuiProjectLoad",
|
"GuiProjectLoad",
|
||||||
|
|||||||
@@ -1,203 +0,0 @@
|
|||||||
"""
|
|
||||||
novelWriter – GUI Item Editor
|
|
||||||
=============================
|
|
||||||
GUI class for the item editor dialog
|
|
||||||
|
|
||||||
File History:
|
|
||||||
Created: 2019-04-27 [0.0.1]
|
|
||||||
|
|
||||||
This file is a part of novelWriter
|
|
||||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import novelwriter
|
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot
|
|
||||||
from PyQt5.QtWidgets import (
|
|
||||||
QDialog, QVBoxLayout, QGridLayout, QLineEdit, QComboBox, QLabel,
|
|
||||||
QDialogButtonBox
|
|
||||||
)
|
|
||||||
|
|
||||||
from novelwriter.enum import nwItemLayout, nwItemType
|
|
||||||
from novelwriter.constants import trConst, nwLabels
|
|
||||||
from novelwriter.gui.custom import QSwitch
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class GuiItemEditor(QDialog):
|
|
||||||
|
|
||||||
def __init__(self, mainGui, tHandle):
|
|
||||||
QDialog.__init__(self, mainGui)
|
|
||||||
|
|
||||||
logger.debug("Initialising GuiItemEditor ...")
|
|
||||||
self.setObjectName("GuiItemEditor")
|
|
||||||
|
|
||||||
self.mainConf = novelwriter.CONFIG
|
|
||||||
self.mainGui = mainGui
|
|
||||||
self.theProject = mainGui.theProject
|
|
||||||
|
|
||||||
##
|
|
||||||
# Build GUI
|
|
||||||
##
|
|
||||||
|
|
||||||
self.theItem = self.theProject.tree[tHandle]
|
|
||||||
if self.theItem is None:
|
|
||||||
self.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
self.setWindowTitle(self.tr("Item Settings"))
|
|
||||||
|
|
||||||
mVd = self.mainConf.pxInt(220)
|
|
||||||
mSp = self.mainConf.pxInt(16)
|
|
||||||
vSp = self.mainConf.pxInt(4)
|
|
||||||
|
|
||||||
# Item Label
|
|
||||||
self.editName = QLineEdit()
|
|
||||||
self.editName.setMinimumWidth(mVd)
|
|
||||||
self.editName.setMaxLength(200)
|
|
||||||
|
|
||||||
# Item Status
|
|
||||||
self.editStatus = QComboBox()
|
|
||||||
self.editStatus.setMinimumWidth(mVd)
|
|
||||||
if self.theItem.isNovelLike():
|
|
||||||
for key, entry in self.theProject.statusItems.items():
|
|
||||||
self.editStatus.addItem(entry["icon"], entry["name"], key)
|
|
||||||
|
|
||||||
index = self.editStatus.findData(self.theItem.itemStatus)
|
|
||||||
if index != -1:
|
|
||||||
self.editStatus.setCurrentIndex(index)
|
|
||||||
|
|
||||||
else:
|
|
||||||
for key, entry in self.theProject.importItems.items():
|
|
||||||
self.editStatus.addItem(entry["icon"], entry["name"], key)
|
|
||||||
|
|
||||||
index = self.editStatus.findData(self.theItem.itemImport)
|
|
||||||
if index != -1:
|
|
||||||
self.editStatus.setCurrentIndex(index)
|
|
||||||
|
|
||||||
# Item Layout
|
|
||||||
self.editLayout = QComboBox()
|
|
||||||
self.editLayout.setMinimumWidth(mVd)
|
|
||||||
validLayouts = []
|
|
||||||
if self.theItem.itemType == nwItemType.FILE:
|
|
||||||
if self.theItem.documentAllowed():
|
|
||||||
validLayouts.append(nwItemLayout.DOCUMENT)
|
|
||||||
validLayouts.append(nwItemLayout.NOTE)
|
|
||||||
else:
|
|
||||||
validLayouts.append(nwItemLayout.NO_LAYOUT)
|
|
||||||
self.editLayout.setEnabled(False)
|
|
||||||
|
|
||||||
for itemLayout in nwItemLayout:
|
|
||||||
if itemLayout in validLayouts:
|
|
||||||
self.editLayout.addItem(trConst(nwLabels.LAYOUT_NAME[itemLayout]), itemLayout)
|
|
||||||
|
|
||||||
index = self.editLayout.findData(self.theItem.itemLayout)
|
|
||||||
if index != -1:
|
|
||||||
self.editLayout.setCurrentIndex(index)
|
|
||||||
|
|
||||||
# Export Switch
|
|
||||||
self.textExport = QLabel(self.tr("Include when building project"))
|
|
||||||
self.editExport = QSwitch()
|
|
||||||
if self.theItem.itemType == nwItemType.FILE:
|
|
||||||
self.editExport.setEnabled(True)
|
|
||||||
self.editExport.setChecked(self.theItem.isExported)
|
|
||||||
else:
|
|
||||||
self.editExport.setEnabled(False)
|
|
||||||
self.editExport.setChecked(False)
|
|
||||||
|
|
||||||
# Buttons
|
|
||||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
|
||||||
self.buttonBox.accepted.connect(self._doSave)
|
|
||||||
self.buttonBox.rejected.connect(self._doClose)
|
|
||||||
|
|
||||||
# Set Current Values
|
|
||||||
self.editName.setText(self.theItem.itemName)
|
|
||||||
self.editName.selectAll()
|
|
||||||
|
|
||||||
##
|
|
||||||
# Assemble
|
|
||||||
##
|
|
||||||
|
|
||||||
nameLabel = QLabel(self.tr("Label"))
|
|
||||||
statusLabel = QLabel(self.tr("Status"))
|
|
||||||
layoutLabel = QLabel(self.tr("Layout"))
|
|
||||||
|
|
||||||
self.mainForm = QGridLayout()
|
|
||||||
self.mainForm.setVerticalSpacing(vSp)
|
|
||||||
self.mainForm.setHorizontalSpacing(mSp)
|
|
||||||
self.mainForm.addWidget(nameLabel, 0, 0, 1, 1)
|
|
||||||
self.mainForm.addWidget(self.editName, 0, 1, 1, 2)
|
|
||||||
self.mainForm.addWidget(statusLabel, 1, 0, 1, 1)
|
|
||||||
self.mainForm.addWidget(self.editStatus, 1, 1, 1, 2)
|
|
||||||
self.mainForm.addWidget(layoutLabel, 2, 0, 1, 1)
|
|
||||||
self.mainForm.addWidget(self.editLayout, 2, 1, 1, 2)
|
|
||||||
self.mainForm.addWidget(self.textExport, 3, 0, 1, 2)
|
|
||||||
self.mainForm.addWidget(self.editExport, 3, 2, 1, 1)
|
|
||||||
self.mainForm.setColumnStretch(0, 0)
|
|
||||||
self.mainForm.setColumnStretch(1, 1)
|
|
||||||
self.mainForm.setColumnStretch(2, 0)
|
|
||||||
|
|
||||||
self.outerBox = QVBoxLayout()
|
|
||||||
self.outerBox.setSpacing(mSp)
|
|
||||||
self.outerBox.addLayout(self.mainForm)
|
|
||||||
self.outerBox.addStretch(1)
|
|
||||||
self.outerBox.addWidget(self.buttonBox)
|
|
||||||
self.setLayout(self.outerBox)
|
|
||||||
|
|
||||||
self.rejected.connect(self._doClose)
|
|
||||||
|
|
||||||
logger.debug("GuiItemEditor initialisation complete")
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
##
|
|
||||||
# Slots
|
|
||||||
##
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doSave(self):
|
|
||||||
"""Save the setting to the item.
|
|
||||||
"""
|
|
||||||
logger.verbose("ItemEditor save button clicked")
|
|
||||||
|
|
||||||
itemName = self.editName.text()
|
|
||||||
itemStatus = self.editStatus.currentData()
|
|
||||||
itemLayout = self.editLayout.currentData()
|
|
||||||
isExported = self.editExport.isChecked()
|
|
||||||
|
|
||||||
self.theItem.setName(itemName)
|
|
||||||
self.theItem.setImportStatus(itemStatus)
|
|
||||||
self.theItem.setLayout(itemLayout)
|
|
||||||
self.theItem.setExported(isExported)
|
|
||||||
|
|
||||||
self.theProject.setProjectChanged(True)
|
|
||||||
|
|
||||||
self.accept()
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doClose(self):
|
|
||||||
"""Close the dialog without saving the settings.
|
|
||||||
"""
|
|
||||||
logger.verbose("ItemEditor cancel button clicked")
|
|
||||||
self.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
# END Class GuiItemEditor
|
|
||||||
@@ -163,8 +163,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.projMenu.addSeparator()
|
self.projMenu.addSeparator()
|
||||||
|
|
||||||
# Project > Edit
|
# Project > Edit
|
||||||
self.aEditItem = QAction(self.tr("Edit Item"), self)
|
self.aEditItem = QAction(self.tr("Rename Item"), self)
|
||||||
self.aEditItem.setShortcuts(["Ctrl+E", "F2"])
|
self.aEditItem.setShortcuts(["F2"])
|
||||||
self.aEditItem.triggered.connect(lambda: self.mainGui.editItem(None))
|
self.aEditItem.triggered.connect(lambda: self.mainGui.editItem(None))
|
||||||
self.projMenu.addAction(self.aEditItem)
|
self.projMenu.addAction(self.aEditItem)
|
||||||
|
|
||||||
|
|||||||
+18
-21
@@ -34,15 +34,15 @@ from time import time
|
|||||||
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtGui import QIcon, QPalette
|
from PyQt5.QtGui import QIcon, QPalette
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QAbstractItemView, QDialog, QFrame, QHBoxLayout, QHeaderView, QInputDialog,
|
QAbstractItemView, QFrame, QHBoxLayout, QHeaderView, QLabel,
|
||||||
QLabel, QMenu, QShortcut, QSizePolicy, QToolButton, QTreeWidget,
|
QMenu, QShortcut, QSizePolicy, QToolButton, QTreeWidget, QTreeWidgetItem,
|
||||||
QTreeWidgetItem, QVBoxLayout, QWidget
|
QVBoxLayout, QWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
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.dialogs.itemeditor import GuiItemEditor
|
|
||||||
from novelwriter.constants import trConst, nwLabels
|
from novelwriter.constants import trConst, nwLabels
|
||||||
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ class GuiProjectView(QWidget):
|
|||||||
|
|
||||||
# Function Mappings
|
# Function Mappings
|
||||||
self.revealNewTreeItem = self.projTree.revealNewTreeItem
|
self.revealNewTreeItem = self.projTree.revealNewTreeItem
|
||||||
self.editTreeItem = self.projTree.editTreeItem
|
self.renameTreeItem = self.projTree.renameTreeItem
|
||||||
self.getTreeFromHandle = self.projTree.getTreeFromHandle
|
self.getTreeFromHandle = self.projTree.getTreeFromHandle
|
||||||
self.emptyTrash = self.projTree.emptyTrash
|
self.emptyTrash = self.projTree.emptyTrash
|
||||||
self.deleteItem = self.projTree.deleteItem
|
self.deleteItem = self.projTree.deleteItem
|
||||||
@@ -470,7 +470,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
else:
|
else:
|
||||||
newLabel = self.tr("New Folder")
|
newLabel = self.tr("New Folder")
|
||||||
|
|
||||||
newLabel, dlgOk = QInputDialog.getText(self, "", self.tr("Label:"), text=newLabel)
|
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=newLabel)
|
||||||
if not dlgOk:
|
if not dlgOk:
|
||||||
logger.info("New item creation cancelled by user")
|
logger.info("New item creation cancelled by user")
|
||||||
return False
|
return False
|
||||||
@@ -565,23 +565,20 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def editTreeItem(self, tHandle):
|
def renameTreeItem(self, tHandle):
|
||||||
"""Open the edit item dialog.
|
"""Open a dialog to edit the label of an item.
|
||||||
"""
|
"""
|
||||||
tItem = self.theProject.tree[tHandle]
|
tItem = self.theProject.tree[tHandle]
|
||||||
if tItem is None:
|
if tItem is None:
|
||||||
return False
|
return False
|
||||||
if tItem.itemType == nwItemType.NO_TYPE:
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.verbose("Requesting change to item '%s'", tHandle)
|
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=tItem.itemName)
|
||||||
dlgProj = GuiItemEditor(self, tHandle)
|
if dlgOk:
|
||||||
dlgProj.exec_()
|
tItem.setName(newLabel)
|
||||||
if dlgProj.result() == QDialog.Accepted:
|
|
||||||
self.setTreeItemValues(tHandle)
|
self.setTreeItemValues(tHandle)
|
||||||
self._alertTreeChange(tHandle=tHandle, flush=False)
|
self._alertTreeChange(tHandle=tHandle, flush=False)
|
||||||
|
|
||||||
return True
|
return
|
||||||
|
|
||||||
def saveTreeOrder(self):
|
def saveTreeOrder(self):
|
||||||
"""Build a list of the items in the project tree and send them
|
"""Build a list of the items in the project tree and send them
|
||||||
@@ -1019,6 +1016,10 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
# Edit Item Settings
|
# Edit Item Settings
|
||||||
# ==================
|
# ==================
|
||||||
|
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Change Label"), lambda: self.renameTreeItem(tHandle)
|
||||||
|
)
|
||||||
|
|
||||||
if isFile:
|
if isFile:
|
||||||
ctxMenu.addAction(
|
ctxMenu.addAction(
|
||||||
self.tr("Toggle Exported"), lambda: self._toggleItemExported(tHandle)
|
self.tr("Toggle Exported"), lambda: self._toggleItemExported(tHandle)
|
||||||
@@ -1057,12 +1058,8 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
ctxMenu.addSeparator()
|
ctxMenu.addSeparator()
|
||||||
|
|
||||||
# Major Item Actions
|
# Delete Item
|
||||||
# ==================
|
# ===========
|
||||||
|
|
||||||
ctxMenu.addAction(
|
|
||||||
self.tr("Edit Item Settings"), lambda: self.editTreeItem(tHandle)
|
|
||||||
)
|
|
||||||
|
|
||||||
if tItem.itemClass == nwItemClass.TRASH or tItem.itemType == nwItemType.ROOT:
|
if tItem.itemClass == nwItemClass.TRASH or tItem.itemType == nwItemType.ROOT:
|
||||||
ctxMenu.addAction(
|
ctxMenu.addAction(
|
||||||
|
|||||||
@@ -817,7 +817,7 @@ class GuiMain(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
tHandle = self.projView.getSelectedHandle()
|
tHandle = self.projView.getSelectedHandle()
|
||||||
if tHandle:
|
if tHandle:
|
||||||
return self.projView.editTreeItem(tHandle)
|
return self.projView.renameTreeItem(tHandle)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ 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, QInputDialog
|
from PyQt5.QtWidgets import QAction, QMessageBox
|
||||||
|
|
||||||
from novelwriter.enum import nwItemType, nwWidget
|
from novelwriter.enum import nwItemType, nwWidget
|
||||||
from novelwriter.dialogs import GuiDocMerge, GuiItemEditor
|
from novelwriter.dialogs import GuiDocMerge, GuiEditLabel
|
||||||
from novelwriter.core.tree import NWTree
|
from novelwriter.core.tree import NWTree
|
||||||
|
|
||||||
|
|
||||||
@@ -39,7 +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))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
|
|
||||||
# Create a new project
|
# Create a new project
|
||||||
buildTestProject(nwGUI, fncProj)
|
buildTestProject(nwGUI, fncProj)
|
||||||
@@ -55,7 +55,6 @@ def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
|||||||
hMergedDoc = "0000000000023"
|
hMergedDoc = "0000000000023"
|
||||||
|
|
||||||
# Add Project Content
|
# Add Project Content
|
||||||
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: QDialog.Accepted)
|
|
||||||
nwGUI.switchFocus(nwWidget.TREE)
|
nwGUI.switchFocus(nwWidget.TREE)
|
||||||
nwGUI.projView.projTree.clearSelection()
|
nwGUI.projView.projTree.clearSelection()
|
||||||
nwGUI.projView.projTree._getTreeItem(hChapterDir).setSelected(True)
|
nwGUI.projView.projTree._getTreeItem(hChapterDir).setSelected(True)
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ 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, QInputDialog
|
from PyQt5.QtWidgets import QAction, QMessageBox
|
||||||
|
|
||||||
from novelwriter.enum import nwItemType, nwWidget
|
from novelwriter.enum import nwItemType, nwWidget
|
||||||
from novelwriter.dialogs import GuiDocSplit, GuiItemEditor
|
from novelwriter.dialogs import GuiDocSplit, GuiEditLabel
|
||||||
from novelwriter.core.tree import NWTree
|
from novelwriter.core.tree import NWTree
|
||||||
from novelwriter.core.document import NWDoc
|
from novelwriter.core.document import NWDoc
|
||||||
|
|
||||||
@@ -40,7 +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))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
|
|
||||||
# Create a new project
|
# Create a new project
|
||||||
buildTestProject(nwGUI, fncProj)
|
buildTestProject(nwGUI, fncProj)
|
||||||
@@ -59,7 +59,6 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
|||||||
hSceneFive = "0000000000028"
|
hSceneFive = "0000000000028"
|
||||||
|
|
||||||
# Add Project Content
|
# Add Project Content
|
||||||
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: QDialog.Accepted)
|
|
||||||
nwGUI.switchFocus(nwWidget.TREE)
|
nwGUI.switchFocus(nwWidget.TREE)
|
||||||
nwGUI.projView.projTree.clearSelection()
|
nwGUI.projView.projTree.clearSelection()
|
||||||
nwGUI.projView.projTree._getTreeItem(hNovelRoot).setSelected(True)
|
nwGUI.projView.projTree._getTreeItem(hNovelRoot).setSelected(True)
|
||||||
|
|||||||
@@ -1,246 +0,0 @@
|
|||||||
"""
|
|
||||||
novelWriter – Item Editor Dialog Class Tester
|
|
||||||
=============================================
|
|
||||||
|
|
||||||
This file is a part of novelWriter
|
|
||||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from tools import getGuiItem, buildTestProject
|
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QAction, QDialog, QMessageBox, QInputDialog
|
|
||||||
|
|
||||||
from novelwriter.enum import nwItemLayout, nwItemType
|
|
||||||
from novelwriter.dialogs import GuiItemEditor
|
|
||||||
from novelwriter.core.tree import NWTree
|
|
||||||
from novelwriter.gui.projtree import GuiProjectTree
|
|
||||||
|
|
||||||
statusKeys = ["s000000", "s000001", "s000002", "s000003"]
|
|
||||||
importKeys = ["i000004", "i000005", "i000006", "i000007"]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
|
||||||
def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
|
||||||
"""Test launching the item editor dialog from GuiMain.
|
|
||||||
"""
|
|
||||||
# Block message box
|
|
||||||
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
|
|
||||||
|
|
||||||
# Block Dialog exec_
|
|
||||||
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: None)
|
|
||||||
|
|
||||||
# Open Editor wo/Project
|
|
||||||
assert nwGUI.editItem() is False
|
|
||||||
|
|
||||||
# Create and Open Project
|
|
||||||
buildTestProject(nwGUI, fncProj)
|
|
||||||
tHandle = "000000000000f"
|
|
||||||
|
|
||||||
# No Selection
|
|
||||||
nwGUI.projView.projTree.clearSelection()
|
|
||||||
assert nwGUI.editItem() is False
|
|
||||||
|
|
||||||
# Force opening from editor
|
|
||||||
assert nwGUI.openDocument(tHandle)
|
|
||||||
nwGUI.isFocusMode = True
|
|
||||||
|
|
||||||
# Block Tree Lookup
|
|
||||||
with monkeypatch.context() as mp:
|
|
||||||
mp.setattr(NWTree, "__getitem__", lambda *a: None)
|
|
||||||
assert nwGUI.editItem() is False
|
|
||||||
|
|
||||||
# Invalid Type
|
|
||||||
nwGUI.theProject.tree[tHandle]._type = nwItemType.NO_TYPE
|
|
||||||
assert nwGUI.editItem() is False
|
|
||||||
nwGUI.theProject.tree[tHandle]._type = nwItemType.FILE
|
|
||||||
|
|
||||||
# Open Properly
|
|
||||||
assert nwGUI.editItem() is True
|
|
||||||
qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000)
|
|
||||||
itemEdit = getGuiItem("GuiItemEditor")
|
|
||||||
assert itemEdit is not None
|
|
||||||
itemEdit.close()
|
|
||||||
|
|
||||||
# Open Via Menu
|
|
||||||
with monkeypatch.context() as mp:
|
|
||||||
mp.setattr(GuiItemEditor, "result", lambda *a: QDialog.Accepted)
|
|
||||||
nwGUI.mainMenu.aEditItem.activate(QAction.Trigger)
|
|
||||||
qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000)
|
|
||||||
itemEdit = getGuiItem("GuiItemEditor")
|
|
||||||
assert itemEdit is not None
|
|
||||||
itemEdit.close()
|
|
||||||
|
|
||||||
nwGUI.isFocusMode = False
|
|
||||||
|
|
||||||
# END Test testDlgItemEditor_Dialog
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
|
||||||
def testDlgItemEditor_Novel(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
|
||||||
"""Test the item editor dialog for a novel document.
|
|
||||||
"""
|
|
||||||
# Block message box
|
|
||||||
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
|
|
||||||
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
|
|
||||||
|
|
||||||
# Create Project and Open Document
|
|
||||||
buildTestProject(nwGUI, fncProj)
|
|
||||||
tHandle = "000000000000f"
|
|
||||||
|
|
||||||
assert nwGUI.theProject.statusItems.name(statusKeys[0]) == "New"
|
|
||||||
assert nwGUI.theProject.statusItems.name(statusKeys[1]) == "Note"
|
|
||||||
|
|
||||||
assert nwGUI.openDocument(tHandle) is True
|
|
||||||
|
|
||||||
# Check that an invalid handle is managed
|
|
||||||
itemEdit = GuiItemEditor(nwGUI, "whatever")
|
|
||||||
itemEdit.show()
|
|
||||||
itemEdit._doClose()
|
|
||||||
|
|
||||||
# Edit a Document
|
|
||||||
itemEdit = GuiItemEditor(nwGUI, tHandle)
|
|
||||||
itemEdit.show()
|
|
||||||
|
|
||||||
# Check Existing Settings
|
|
||||||
assert itemEdit.editName.text() == "New Scene"
|
|
||||||
assert itemEdit.editStatus.currentData() == statusKeys[0]
|
|
||||||
assert itemEdit.editLayout.currentData() == nwItemLayout.DOCUMENT
|
|
||||||
assert itemEdit.editExport.isChecked() is True
|
|
||||||
|
|
||||||
# Change Settings
|
|
||||||
layoutIdx = itemEdit.editLayout.findData(nwItemLayout.NOTE)
|
|
||||||
itemEdit.editName.setText("Great Scene")
|
|
||||||
itemEdit.editStatus.setCurrentIndex(1)
|
|
||||||
itemEdit.editLayout.setCurrentIndex(layoutIdx)
|
|
||||||
itemEdit.editExport.setChecked(False)
|
|
||||||
|
|
||||||
# Check New Settings
|
|
||||||
itemEdit._doSave()
|
|
||||||
assert itemEdit.theItem.itemName == "Great Scene"
|
|
||||||
assert itemEdit.theItem.itemStatus == statusKeys[1]
|
|
||||||
assert itemEdit.theItem.itemLayout == nwItemLayout.NOTE
|
|
||||||
assert itemEdit.theItem.isExported is False
|
|
||||||
|
|
||||||
# Check that the editor header is updated
|
|
||||||
nwGUI.docEditor.updateDocInfo(tHandle)
|
|
||||||
assert nwGUI.docEditor.docHeader.theTitle.text() == "Novel › New Chapter › Great Scene"
|
|
||||||
|
|
||||||
itemEdit.close()
|
|
||||||
del itemEdit
|
|
||||||
# qtbot.stopForInteraction()
|
|
||||||
|
|
||||||
# END Test testDlgItemEditor_Dialog
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
|
||||||
def testDlgItemEditor_Note(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
|
||||||
"""Test the item editor dialog for a project note.
|
|
||||||
"""
|
|
||||||
# Block message box
|
|
||||||
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
|
|
||||||
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
|
|
||||||
monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
|
|
||||||
|
|
||||||
# Create Project and Open Document
|
|
||||||
buildTestProject(nwGUI, fncProj)
|
|
||||||
assert nwGUI.theProject.statusItems.name(statusKeys[0]) == "New"
|
|
||||||
assert nwGUI.theProject.statusItems.name(statusKeys[1]) == "Note"
|
|
||||||
assert nwGUI.theProject.importItems.name(importKeys[0]) == "New"
|
|
||||||
assert nwGUI.theProject.importItems.name(importKeys[1]) == "Minor"
|
|
||||||
|
|
||||||
# Create Note
|
|
||||||
nwGUI.projView.projTree.clearSelection()
|
|
||||||
nwGUI.projView.projTree._getTreeItem("000000000000a").setSelected(True)
|
|
||||||
nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, None, isNote=True)
|
|
||||||
|
|
||||||
# Open Note
|
|
||||||
assert nwGUI.openDocument("0000000000010")
|
|
||||||
|
|
||||||
# Edit a Document
|
|
||||||
itemEdit = GuiItemEditor(nwGUI, "0000000000010")
|
|
||||||
itemEdit.show()
|
|
||||||
|
|
||||||
# Check Existing Settings
|
|
||||||
assert itemEdit.editName.text() == "New Note"
|
|
||||||
assert itemEdit.editStatus.currentData() == importKeys[0]
|
|
||||||
assert itemEdit.editLayout.currentData() == nwItemLayout.NOTE
|
|
||||||
assert itemEdit.editExport.isChecked() is True
|
|
||||||
|
|
||||||
# Change Settings
|
|
||||||
itemEdit.editName.setText("New Character")
|
|
||||||
itemEdit.editStatus.setCurrentIndex(1)
|
|
||||||
itemEdit.editExport.setChecked(False)
|
|
||||||
itemEdit._doSave()
|
|
||||||
|
|
||||||
# Check New Settings
|
|
||||||
assert itemEdit.theItem.itemName == "New Character"
|
|
||||||
assert itemEdit.theItem.itemStatus == statusKeys[0]
|
|
||||||
assert itemEdit.theItem.itemImport == importKeys[1]
|
|
||||||
assert itemEdit.theItem.itemLayout == nwItemLayout.NOTE
|
|
||||||
assert itemEdit.theItem.isExported is False
|
|
||||||
|
|
||||||
itemEdit.close()
|
|
||||||
del itemEdit
|
|
||||||
# qtbot.stopForInteraction()
|
|
||||||
|
|
||||||
# END Test testDlgItemEditor_Note
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
|
||||||
def testDlgItemEditor_Folder(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
|
||||||
"""Test the item editor dialog for a folder.
|
|
||||||
"""
|
|
||||||
# Block message box
|
|
||||||
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
|
|
||||||
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
|
|
||||||
|
|
||||||
# Create Project and Open Document
|
|
||||||
buildTestProject(nwGUI, fncProj)
|
|
||||||
|
|
||||||
# Edit a Folder
|
|
||||||
itemEdit = GuiItemEditor(nwGUI, "000000000000d")
|
|
||||||
itemEdit.show()
|
|
||||||
|
|
||||||
assert nwGUI.theProject.statusItems.name(statusKeys[0]) == "New"
|
|
||||||
assert nwGUI.theProject.statusItems.name(statusKeys[1]) == "Note"
|
|
||||||
|
|
||||||
# Check Existing Settings
|
|
||||||
assert itemEdit.editName.text() == "New Chapter"
|
|
||||||
assert itemEdit.editStatus.currentData() == statusKeys[0]
|
|
||||||
assert itemEdit.editLayout.currentData() == nwItemLayout.NO_LAYOUT
|
|
||||||
assert itemEdit.editExport.isChecked() is False
|
|
||||||
|
|
||||||
assert itemEdit.editLayout.isEnabled() is False
|
|
||||||
assert itemEdit.editExport.isEnabled() is False
|
|
||||||
|
|
||||||
# Change Settings
|
|
||||||
itemEdit.editName.setText("Chapter One")
|
|
||||||
itemEdit.editStatus.setCurrentIndex(1)
|
|
||||||
|
|
||||||
# Check New Settings
|
|
||||||
itemEdit._doSave()
|
|
||||||
assert itemEdit.theItem.itemName == "Chapter One"
|
|
||||||
assert itemEdit.theItem.itemStatus == statusKeys[1]
|
|
||||||
assert itemEdit.theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
|
||||||
assert itemEdit.theItem.isExported is False
|
|
||||||
|
|
||||||
itemEdit.close()
|
|
||||||
del itemEdit
|
|
||||||
# qtbot.stopForInteraction()
|
|
||||||
|
|
||||||
# END Test testDlgItemEditor_Folder
|
|
||||||
@@ -26,13 +26,13 @@ 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, QInputDialog
|
from PyQt5.QtWidgets import QMessageBox, QInputDialog
|
||||||
|
|
||||||
from novelwriter.gui import GuiDocEditor, GuiNovelTree, GuiOutlineView
|
from novelwriter.gui import GuiDocEditor, GuiNovelTree, GuiOutlineView
|
||||||
from novelwriter.enum import nwItemType, nwWidget
|
from novelwriter.enum import nwItemType, nwWidget
|
||||||
from novelwriter.tools import GuiProjectWizard
|
from novelwriter.tools import GuiProjectWizard
|
||||||
from novelwriter.gui.projtree import GuiProjectTree
|
from novelwriter.gui.projtree import GuiProjectTree
|
||||||
from novelwriter.dialogs.itemeditor import GuiItemEditor
|
from novelwriter.dialogs import GuiEditLabel
|
||||||
|
|
||||||
keyDelay = 2
|
keyDelay = 2
|
||||||
typeDelay = 1
|
typeDelay = 1
|
||||||
@@ -169,11 +169,10 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
|
|||||||
# 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, "information", lambda *a: QMessageBox.Yes)
|
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
|
||||||
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: None)
|
|
||||||
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))
|
monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
|
||||||
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
|
|
||||||
# Create new, save, close project
|
# Create new, save, close project
|
||||||
buildTestProject(nwGUI, fncProj)
|
buildTestProject(nwGUI, fncProj)
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ import os
|
|||||||
|
|
||||||
from tools import buildTestProject
|
from tools import buildTestProject
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QMessageBox, QInputDialog, QMenu
|
from PyQt5.QtWidgets import QMessageBox, QMenu
|
||||||
|
|
||||||
from novelwriter.gui.projtree import GuiProjectTree
|
|
||||||
from novelwriter.enum import nwItemLayout, nwItemType, nwItemClass
|
from novelwriter.enum import nwItemLayout, nwItemType, nwItemClass
|
||||||
|
from novelwriter.dialogs import GuiEditLabel
|
||||||
|
from novelwriter.gui.projtree import GuiProjectTree
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
@@ -39,7 +40,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(QInputDialog, "getText", lambda *a, text: (text, True))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
|
|
||||||
nwTree = nwGUI.projView
|
nwTree = nwGUI.projView
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
|
|||||||
|
|
||||||
# Cancel during creation
|
# Cancel during creation
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr(QInputDialog, "getText", lambda *a, **k: ("", False))
|
mp.setattr(GuiEditLabel, "getLabel", lambda *a, **k: ("", False))
|
||||||
nwTree.setSelectedHandle("0000000000013")
|
nwTree.setSelectedHandle("0000000000013")
|
||||||
assert nwTree.projTree.newTreeItem(nwItemType.FILE) is False
|
assert nwTree.projTree.newTreeItem(nwItemType.FILE) is False
|
||||||
|
|
||||||
@@ -162,7 +163,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(QInputDialog, "getText", lambda *a, text: (text, True))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
|
|
||||||
nwTree = nwGUI.projView
|
nwTree = nwGUI.projView
|
||||||
|
|
||||||
@@ -277,7 +278,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(QInputDialog, "getText", lambda *a, text: (text, True))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
|
|
||||||
nwTree = nwGUI.projView
|
nwTree = nwGUI.projView
|
||||||
|
|
||||||
@@ -466,7 +467,7 @@ def testGuiProjTree_ContextMenu(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(QInputDialog, "getText", lambda *a, text: (text, True))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
monkeypatch.setattr(QMenu, "exec_", lambda *a: None)
|
monkeypatch.setattr(QMenu, "exec_", lambda *a: None)
|
||||||
|
|
||||||
# Create a project
|
# Create a project
|
||||||
|
|||||||
Reference in New Issue
Block a user