Merge pull request #632 from vkbo/actions_refactoring

Menu Actions Refactoring and Extension
This commit is contained in:
Veronica K. Berglyd Olsen
2021-01-31 22:07:09 +00:00
committed by GitHub
18 changed files with 218 additions and 151 deletions
+1
View File
@@ -23,6 +23,7 @@ __pycache__
/sample/meta
*.bak
*.lock
ToC.txt
# PyTest
/prof/
+3 -3
View File
@@ -378,6 +378,8 @@ Most features are available as keyboard shortcuts. These are as follows:
":kbd:`Ctrl`:kbd:`F7`", "Toggle spell checking."
":kbd:`Ctrl`:kbd:`F10`", "Toggle automatic updating of project outline."
":kbd:`Ctrl`:kbd:`Del`", "If in the project tree, move a document to trash, or delete a folder."
":kbd:`Ctrl`:kbd:`Up`", "Move item one step up in the project tree."
":kbd:`Ctrl`:kbd:`Down`", "Move item one step down in the project tree."
":kbd:`Ctrl`:kbd:`'`", "Wrap selected text, or word under cursor, in single quotes."
":kbd:`Ctrl`:kbd:`""`", "Wrap selected text, or word under cursor, in double quotes."
":kbd:`Ctrl`:kbd:`Enter`", "Open the tag or reference under the cursor in the Viewer."
@@ -392,9 +394,7 @@ Most features are available as keyboard shortcuts. These are as follows:
":kbd:`Ctrl`:kbd:`Shift`:kbd:`R`", "Close the document viewer."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`S`", "Save the current project."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`W`", "Close the current project."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`Z`", "Alternative sequence for redo last undo."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`Up`", "Move item one step up in the project tree."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`Down`", "Move item one step down in the project tree."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`Z`", "Undo move of project tree item."
":kbd:`F1`", "Open the documentation. This will either open the Qt Assistant, if available, or send you to the documentation website."
":kbd:`F2`", "If in the project tree, edit a document or folder settings. (Same as :kbd:`Ctrl`:kbd:`E`)"
":kbd:`F3`", "Find next occurrence of search word in current document. (Same as :kbd:`Ctrl`:kbd:`G`)"
+3 -1
View File
@@ -49,13 +49,15 @@ class nwConst():
class nwLists():
"""Lists used for grouping various other constants.
"""
# Regular user-accessible item types
REG_TYPES = {nwItemType.ROOT, nwItemType.FOLDER, nwItemType.FILE}
# Item classes where the full list of novel layouts are allowed
CLS_NOVEL = {nwItemClass.NOVEL, nwItemClass.ARCHIVE}
# Item classes which do not require items to have same class
FREE_CLASS = {nwItemClass.ARCHIVE, nwItemClass.TRASH}
# END Class nwLists
class nwRegEx():
+4
View File
@@ -646,6 +646,10 @@ class GuiDocEditor(QTextEdit):
this class when calling these actions from other classes.
"""
logger.verbose("Requesting action: %s" % theAction.name)
if not self.hasFocus():
logger.verbose("Editor does not have focus")
return False
if self.theHandle is None:
logger.error("No document open")
return False
+35 -34
View File
@@ -115,22 +115,25 @@ class GuiMainMenu(QMenuBar):
##
def setSpellCheck(self, theMode):
"""Set the spell check check box to theMode. This is controlled
by the document editor class, which holds the master spell check
flag.
"""Forward spell check check state to its action.
"""
self.aSpellCheck.setChecked(theMode)
return
def setAutoOutline(self, theMode):
"""Set the auto outline check box to theMode. Used during
initialisation.
"""Forward auto outline check state to its action.
"""
self.aAutoOutline.setChecked(theMode)
return
def setFocusMode(self, theMode):
"""Forward focus mode check state to its action.
"""
self.aFocusMode.setChecked(theMode)
return
##
# Menu Action
# Slots
##
def _toggleSpellCheck(self, isChecked=False):
@@ -164,17 +167,11 @@ class GuiMainMenu(QMenuBar):
return True
def _openWebsite(self, theUrl):
"""Open an URL in the system's default browser.
"""Open a URL in the system's default browser.
"""
QDesktopServices.openUrl(QUrl(theUrl))
return True
def _openIssue(self):
"""Open the issue tracker URL in the system's default browser.
"""
QDesktopServices.openUrl(QUrl(nw.__issuesurl__))
return True
##
# Menu Builders
##
@@ -263,19 +260,40 @@ class GuiMainMenu(QMenuBar):
self.projMenu.addSeparator()
# Project > Edit
self.aEditItem = QAction("Edit Project Item", self)
self.aEditItem.setStatusTip("Change item settings")
self.aEditItem = QAction("Edit Item", self)
self.aEditItem.setStatusTip("Change project item settings")
self.aEditItem.setShortcuts(["Ctrl+E", "F2"])
self.aEditItem.triggered.connect(lambda: self.theParent.editItem(None))
self.projMenu.addAction(self.aEditItem)
# Project > Delete
self.aDeleteItem = QAction("Delete Project Item", self)
self.aDeleteItem.setStatusTip("Delete selected item")
self.aDeleteItem = QAction("Delete Item", self)
self.aDeleteItem.setStatusTip("Delete selected project item")
self.aDeleteItem.setShortcut("Ctrl+Del")
self.aDeleteItem.triggered.connect(lambda: self.theParent.treeView.deleteItem(None))
self.projMenu.addAction(self.aDeleteItem)
# Project > Move Up
self.aMoveUp = QAction("Move Item Up", self)
self.aMoveUp.setStatusTip("Move project item up")
self.aMoveUp.setShortcut("Ctrl+Up")
self.aMoveUp.triggered.connect(lambda: self._moveTreeItem(-1))
self.projMenu.addAction(self.aMoveUp)
# Project > Move Down
self.aMoveDown = QAction("Move Item Down", self)
self.aMoveDown.setStatusTip("Move project item down")
self.aMoveDown.setShortcut("Ctrl+Down")
self.aMoveDown.triggered.connect(lambda: self._moveTreeItem(1))
self.projMenu.addAction(self.aMoveDown)
# Project > Undo Last Action
self.aMoveUndo = QAction("Undo Last Move", self)
self.aMoveUndo.setStatusTip("Undo last item move")
self.aMoveUndo.setShortcut("Ctrl+Shift+Z")
self.aMoveUndo.triggered.connect(lambda: self.theParent.treeView.undoLastMove())
self.projMenu.addAction(self.aMoveUndo)
# Project > Empty Trash
self.aEmptyTrash = QAction("Empty Trash", self)
self.aEmptyTrash.setStatusTip("Permanently delete all files in the Trash folder")
@@ -891,23 +909,6 @@ class GuiMainMenu(QMenuBar):
# Tools
self.toolsMenu = self.addMenu("&Tools")
# Tools > Move Up
self.aMoveUp = QAction("Move Tree Item Up", self)
self.aMoveUp.setStatusTip("Move item up")
self.aMoveUp.setShortcut("Ctrl+Shift+Up")
self.aMoveUp.triggered.connect(lambda: self._moveTreeItem(-1))
self.toolsMenu.addAction(self.aMoveUp)
# Tools > Move Down
self.aMoveDown = QAction("Move Tree Item Down", self)
self.aMoveDown.setStatusTip("Move item down")
self.aMoveDown.setShortcut("Ctrl+Shift+Down")
self.aMoveDown.triggered.connect(lambda: self._moveTreeItem(1))
self.toolsMenu.addAction(self.aMoveDown)
# Tools > Separator
self.toolsMenu.addSeparator()
# Tools > Toggle Spell Check
self.aSpellCheck = QAction("Check Spelling", self)
self.aSpellCheck.setStatusTip("Toggle check spelling")
+138 -49
View File
@@ -33,12 +33,12 @@ from time import time
from PyQt5.QtCore import Qt, QSize, pyqtSignal
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (
qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction
)
from nw.core import NWDoc
from nw.constants import (
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert, nwConst
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert, nwConst, nwLists
)
logger = logging.getLogger(__name__)
@@ -68,6 +68,7 @@ class GuiProjectTree(QTreeWidget):
self._treeMap = {}
self._treeChanged = False
self._timeChanged = 0
self._lastMove = {}
##
# Build GUI
@@ -297,10 +298,10 @@ class GuiProjectTree(QTreeWidget):
# Save the text and index it
newDoc.saveDocument(newText)
self.theParent.theIndex.scanText(tHandle, newText)
self.theIndex.scanText(tHandle, newText)
# Get Word Counts
cC, wC, pC = self.theParent.theIndex.getCounts(tHandle)
cC, wC, pC = self.theIndex.getCounts(tHandle)
nwItem.setCharCount(cC)
nwItem.setWordCount(wC)
nwItem.setParaCount(pC)
@@ -335,7 +336,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("No project open")
return False
if qApp.focusWidget() != self:
if not self.hasFocus():
return False
tHandle = self.getSelectedHandle()
@@ -361,6 +362,7 @@ class GuiProjectTree(QTreeWidget):
return False
cItem = pItem.takeChild(tIndex)
pItem.insertChild(nIndex, cItem)
self._recordLastMove(cItem, pItem, tIndex)
self.clearSelection()
cItem.setSelected(True)
@@ -517,8 +519,9 @@ class GuiProjectTree(QTreeWidget):
theDoc = NWDoc(self.theProject, self.theParent)
theDoc.deleteDocument(tHandle)
del self.theProject.projTree[tHandle]
self.theIndex.deleteHandle(tHandle)
self._deleteTreeItem(tHandle)
self._setTreeChanged(True)
else:
# The file is not already in the trash folder, so we
@@ -541,11 +544,12 @@ class GuiProjectTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS)
trItemC = trItemP.takeChild(tIndex)
trItemT.addChild(trItemC)
nwItemS.setParent(self.theProject.projTree.trashRoot())
self._updateItemParent(tHandle)
self.propagateCount(tHandle, wCount)
self._setTreeChanged(True)
self.theIndex.deleteHandle(tHandle)
self._recordLastMove(trItemS, trItemP, tIndex)
self._setTreeChanged(True)
elif nwItemS.itemType == nwItemType.FOLDER:
logger.debug("User requested folder %s deleted" % tHandle)
@@ -556,7 +560,8 @@ class GuiProjectTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS)
if trItemS.childCount() == 0:
trItemP.takeChild(tIndex)
del self.theProject.projTree[tHandle]
self._deleteTreeItem(tHandle)
self._setTreeChanged(True)
else:
self.makeAlert((
"Cannot delete folder. It is not empty. "
@@ -570,7 +575,7 @@ class GuiProjectTree(QTreeWidget):
tIndex = self.indexOfTopLevelItem(trItemS)
if trItemS.childCount() == 0:
self.takeTopLevelItem(tIndex)
del self.theProject.projTree[tHandle]
self._deleteTreeItem(tHandle)
self.theParent.mainMenu.setAvailableRoot()
self._setTreeChanged(True)
else:
@@ -679,6 +684,52 @@ class GuiProjectTree(QTreeWidget):
logger.debug("%d items added to the project tree" % iCount)
return True
def undoLastMove(self):
"""Attempt to undo the last action.
"""
srcItem = self._lastMove.get("item", None)
dstItem = self._lastMove.get("parent", None)
dstIndex = self._lastMove.get("index", None)
if not self.hasFocus():
return False
if srcItem is None or dstItem is None or dstIndex is None:
logger.verbose("No tree move to undo")
return False
if srcItem not in self._treeMap.values():
logger.warning("Source item no longer exists")
return False
if dstItem not in self._treeMap.values():
logger.warning("Previous parent item no longer exists")
return False
dstIndex = min(max(0, dstIndex), dstItem.childCount())
wCount = int(srcItem.data(self.C_COUNT, Qt.UserRole))
sHandle = srcItem.data(self.C_NAME, Qt.UserRole)
dHandle = dstItem.data(self.C_NAME, Qt.UserRole)
logger.debug("Moving item %s back to %s, index %d" % (
sHandle, dHandle, dstIndex
))
self.propagateCount(sHandle, 0)
parItem = srcItem.parent()
srcIndex = parItem.indexOfChild(srcItem)
movItem = parItem.takeChild(srcIndex)
dstItem.insertChild(dstIndex, movItem)
snItem = self.theProject.projTree[sHandle]
dnItem = self.theProject.projTree[dHandle]
self._postItemMove(sHandle, snItem, dnItem, wCount)
self.clearSelection()
movItem.setSelected(True)
self._lastMove = {}
return True
def getSelectedHandle(self):
"""Get the currently selected handle. If multiple items are
selected, return the first.
@@ -787,46 +838,30 @@ class GuiProjectTree(QTreeWidget):
self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR)
return
pItem = sItem.parent()
pIndex = 0
if pItem is not None:
pIndex = pItem.indexOfChild(sItem)
wCount = int(sItem.data(self.C_COUNT, Qt.UserRole))
isFile = snItem.itemType == nwItemType.FILE
isRoot = snItem.itemType == nwItemType.ROOT
onFile = dnItem.itemType == nwItemType.FILE
isSame = snItem.itemClass == dnItem.itemClass
isNone = snItem.itemClass == nwItemClass.NO_CLASS
isNote = snItem.itemLayout == nwItemLayout.NOTE
onFile = dnItem.itemType == nwItemType.FILE
isRoot = snItem.itemType == nwItemType.ROOT
onFree = dnItem.itemClass == nwItemClass.ARCHIVE
onFree |= dnItem.itemClass == nwItemClass.TRASH
onFree &= snItem.itemType == nwItemType.FILE
isOnTop = self.dropIndicatorPosition() == QAbstractItemView.OnItem
if (isSame or isNone or isNote or onFree) and not (onFile and isOnTop) and not isRoot:
onFree = dnItem.itemClass in nwLists.FREE_CLASS and isFile
allowDrop = isSame or isNone or isNote or onFree
allowDrop &= not (self.dropIndicatorPosition() == QAbstractItemView.OnItem and onFile)
if allowDrop and not isRoot:
logger.debug("Drag'n'drop of item %s accepted" % sHandle)
self.propagateCount(sHandle, 0)
QTreeWidget.dropEvent(self, theEvent)
self._updateItemParent(sHandle)
# If the item does not have the same class as the target,
# and the target is not a free root folder, update its class
if not (isSame or onFree):
logger.debug("Item %s class has been changed from %s to %s" % (
sHandle,
snItem.itemClass.name,
dnItem.itemClass.name
))
snItem.setClass(dnItem.itemClass)
self.setTreeItemValues(sHandle)
self.propagateCount(sHandle, wCount)
# The items dropped into archive or trash should be removed
# from the project index, for all other items, we rescan the
# file to ensure the index is up to date.
if onFree:
self.theIndex.deleteHandle(sHandle)
else:
self.theIndex.reIndexHandle(sHandle)
# Trigger dependent updates
self._setTreeChanged(True)
self._emitItemChange(sHandle)
self._postItemMove(sHandle, snItem, dnItem, wCount)
self._recordLastMove(sItem, pItem, pIndex)
else:
theEvent.ignore()
@@ -839,22 +874,63 @@ class GuiProjectTree(QTreeWidget):
# Internal Functions
##
def _postItemMove(self, sHandle, snItem, dnItem, wCount):
"""Run various maintenance tasks for a moved item.
"""
isFile = snItem.itemType == nwItemType.FILE
isSame = snItem.itemClass == dnItem.itemClass
onFree = dnItem.itemClass in nwLists.FREE_CLASS and isFile
self._updateItemParent(sHandle)
# If the item does not have the same class as the target,
# and the target is not a free root folder, update its class
if not (isSame or onFree):
logger.debug("Item %s class has been changed from %s to %s" % (
sHandle, snItem.itemClass.name, dnItem.itemClass.name
))
snItem.setClass(dnItem.itemClass)
self.setTreeItemValues(sHandle)
self.propagateCount(sHandle, wCount)
# The items dropped into archive or trash should be removed
# from the project index, for all other items, we rescan the
# file to ensure the index is up to date.
if onFree:
self.theIndex.deleteHandle(sHandle)
else:
self.theIndex.reIndexHandle(sHandle)
# Trigger dependent updates
self._setTreeChanged(True)
self._emitItemChange(sHandle)
return
def _getTreeItem(self, tHandle):
"""Returns the QTreeWidgetItem of a given item handle.
"""
return self._treeMap.get(tHandle, None)
def _scanChildren(self, theList, theItem, theIndex):
def _deleteTreeItem(self, tHandle):
"""Delete a tree item from the project and the map.
"""
del self.theProject.projTree[tHandle]
self._treeMap.pop(tHandle, None)
return
def _scanChildren(self, theList, tItem, tIndex):
"""This is a recursive function returning all items in a tree
starting at a given QTreeWidgetItem.
"""
tHandle = theItem.data(self.C_NAME, Qt.UserRole)
tHandle = tItem.data(self.C_NAME, Qt.UserRole)
nwItem = self.theProject.projTree[tHandle]
nwItem.setExpanded(theItem.isExpanded())
nwItem.setOrder(theIndex)
nwItem.setExpanded(tItem.isExpanded())
nwItem.setOrder(tIndex)
theList.append(tHandle)
for i in range(theItem.childCount()):
self._scanChildren(theList, theItem.child(i), i)
for i in range(tItem.childCount()):
self._scanChildren(theList, tItem.child(i), i)
return theList
def _addTreeItem(self, nwItem, nHandle=None):
@@ -984,6 +1060,19 @@ class GuiProjectTree(QTreeWidget):
return
def _recordLastMove(self, srcItem, parItem, parIndex):
"""Record the last action so that it can be undone.
"""
prevItem = self._lastMove.get("item", None)
if prevItem is None or srcItem != prevItem:
self._lastMove = {
"item": srcItem,
"parent": parItem,
"index": parIndex,
}
return
# END Class GuiProjectTree
class GuiProjectTreeMenu(QMenu):
+2 -2
View File
@@ -1167,11 +1167,11 @@ class GuiMain(QMainWindow):
"""
if self.docEditor.theHandle is None:
logger.error("No document open, so not activating Focus Mode")
self.mainMenu.aFocusMode.setChecked(self.isFocusMode)
self.mainMenu.setFocusMode(self.isFocusMode)
return False
self.isFocusMode = not self.isFocusMode
self.mainMenu.aFocusMode.setChecked(self.isFocusMode)
self.mainMenu.setFocusMode(self.isFocusMode)
if self.isFocusMode:
logger.debug("Activating Focus Mode")
self.mainTabs.setCurrentWidget(self.splitDocs)
-23
View File
@@ -1,23 +0,0 @@
Table of Contents
=================
File Name Class Layout Document Label
---------------------------------------------------------------------
content/53b69b83cdafc.nwd NOVEL TITLE Title Page
content/974e400180a99.nwd NOVEL PAGE Page
content/edca4be2fcaf8.nwd NOVEL PARTITION Part One
content/6a2d6d5f4f401.nwd NOVEL CHAPTER Chapter One
content/636b6aa9b697b.nwd NOVEL SCENE Making a Scene
content/bc0cbd2a407f3.nwd NOVEL SCENE Another Scene
content/ba8a28a246524.nwd NOVEL UNNUMBERED Interlude
content/96b68994dfa3d.nwd NOVEL NOTE A Note on Structure
content/88706ddc78b1b.nwd NOVEL CHAPTER Chapter Two
content/ae7339df26ded.nwd NOVEL SCENE We Found John!
content/14298de4d9524.nwd CHARACTER NOTE John Smith
content/bb2c23b3c42cc.nwd CHARACTER NOTE Jane Smith
content/b3e74dbc1f584.nwd WORLD NOTE Earth
content/f1471bef9f2ae.nwd WORLD NOTE Space
content/5eaea4e8cdee8.nwd WORLD NOTE Mars
content/8a5deb88c0e97.nwd NOVEL SCENE Old File
content/b8136a5a774a0.nwd NOVEL SCENE Delete Me!
+4 -4
View File
@@ -1,13 +1,13 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="1.1rc1" hexVersion="0x010100c1" fileVersion="1.2" timeStamp="2021-01-31 18:12:05">
<novelWriterXML appVersion="1.2a0" hexVersion="0x010200a0" fileVersion="1.2" timeStamp="2021-01-31 22:28:54">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>874</saveCount>
<saveCount>881</saveCount>
<autoCount>157</autoCount>
<editTime>42533</editTime>
<editTime>42668</editTime>
</project>
<settings>
<doBackup>False</doBackup>
@@ -117,7 +117,7 @@
<status>1st Draft</status>
<exported>True</exported>
<layout>SCENE</layout>
<charCount>1811</charCount>
<charCount>1810</charCount>
<wordCount>318</wordCount>
<paraCount>8</paraCount>
<cursorPos>1880</cursorPos>
-22
View File
@@ -1,22 +0,0 @@
Table of Contents
===================
File Name Class Document Label
--------------------------------------------------------------------------------
content/04468803b92e1.nwd WORLD Ancient Europe
content/2426c6f0ca922.nwd PLOT Main
content/441420a886d82.nwd NOVEL Chapter Two
content/47666c91c7ccf.nwd NOVEL Scene Five
content/4c4f28287af27.nwd CHARACTER Mr. Nobody
content/7a992350f3eb6.nwd NOVEL Lorem Ipsum
content/846352075de7d.nwd NOVEL Interlude
content/88243afbe5ed8.nwd NOVEL Scene One
content/88d59a277361b.nwd NOVEL Prologue
content/8c58a65414c23.nwd NOVEL Front Matter
content/db7e733775d4d.nwd NOVEL Act One
content/eb103bc70c90c.nwd NOVEL Scene Three
content/f8c0562e50f1b.nwd NOVEL Scene Four
content/f96ec11c6a3da.nwd NOVEL Scene Two
content/fb609cd8319dc.nwd NOVEL Chapter One
-10
View File
@@ -1,10 +0,0 @@
Table of Contents
===================
File Name Class Document Label
--------------------------------------------------------------------------------
content/8c659a11cd429.nwd NOVEL New Scene
content/a35baf2e93843.nwd NOVEL Title Page
content/f5ab3e30151e1.nwd NOVEL New Chapter
+8 -1
View File
@@ -28,8 +28,10 @@ from tools import cmpFiles
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import QAction, QMessageBox
from PyQt5.QtWidgets import QAction, QMessageBox, QDialog
from nw.gui.itemeditor import GuiItemEditor
from nw.gui.doceditor import GuiDocEditor
from nw.gui.projtree import GuiProjectTree
from nw.constants import nwItemType, nwDocAction
@@ -43,7 +45,11 @@ def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir, outDi
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *args: None)
monkeypatch.setattr(GuiItemEditor, "result", lambda *args: QDialog.Accepted)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True)
monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *args: True)
# Create new, save, close project
nwGUI.theProject.projTree.setSeed(42)
@@ -353,6 +359,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *args: True)
nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.openProject(nwLipsum)
+1
View File
@@ -38,6 +38,7 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
# Open project
nwGUI.theProject.projTree.setSeed(42)
+2
View File
@@ -27,6 +27,7 @@ from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor, QTextBlock
from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox
from nw.gui.doceditor import GuiDocEditor
from nw.constants import nwUnicode, nwDocAction, nwDocInsert, nwKeyWords
keyDelay = 2
@@ -39,6 +40,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, nwLipsum):
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *args: True)
# Test Document Action with No Project
assert not nwGUI.docEditor.docAction(nwDocAction.COPY)
+1
View File
@@ -37,6 +37,7 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
assert nwGUI.openProject(nwLipsum)
nwGUI.mainConf.lastPath = nwLipsum
+1
View File
@@ -48,6 +48,7 @@ def testGuiProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
# Check that we cannot open when there is no project
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
+14 -2
View File
@@ -38,6 +38,9 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(GuiMain, "editItem", lambda *args: None)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True)
@@ -96,12 +99,12 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
nwTree.setSelectedHandle("8c659a11cd429")
# Shift focus and try to move item
monkeypatch.setattr("PyQt5.QtWidgets.qApp.focusWidget", lambda: None)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: False)
assert not nwTree.moveTreeItem(1)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "44cb730c42048", "71ee45a3c0db9"
]
monkeypatch.setattr("PyQt5.QtWidgets.qApp.focusWidget", lambda: nwTree)
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True)
# Move second item up twice (should give same result)
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
@@ -131,6 +134,15 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
"a6d311a93600a", "f5ab3e30151e1", "44cb730c42048", "71ee45a3c0db9", "8c659a11cd429"
]
# Move up twice, and undo
nwTree._lastMove = {}
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
nwGUI.mainMenu.aMoveUndo.activate(QAction.Trigger)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "44cb730c42048", "71ee45a3c0db9", "8c659a11cd429"
]
# Move a root item (top level items are different) twice
nwTree.flushTreeOrder()
assert nwGUI.theProject.projTree._treeOrder.index("9d5247ab588e0") == 10
+1
View File
@@ -46,6 +46,7 @@ def testGuiProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes)
if sys.platform.startswith("darwin"):
# Disable for macOS because the test segfaults on QWizard.show()