Fix merge conflicts

This commit is contained in:
Veronica K. B. Olsen
2020-02-27 00:19:18 +01:00
52 changed files with 1835 additions and 584 deletions
-5
View File
@@ -23,11 +23,6 @@ logger = logging.getLogger(__name__)
class GuiDocDetails(QFrame):
C_NAME = 0
C_COUNT = 1
C_FLAGS = 2
C_HANDLE = 3
def __init__(self, theParent, theProject):
QFrame.__init__(self, theParent)
+23 -14
View File
@@ -21,13 +21,13 @@ from PyQt5.QtWidgets import (
)
from PyQt5.QtGui import (
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette,
QTextDocument
QTextDocument, QCursor
)
from nw.project import NWDoc
from nw.gui.tools import GuiDocHighlighter, WordCounter
from nw.tools import NWSpellCheck, NWSpellSimple
from nw.constants import nwFiles, nwUnicode, nwDocAction, nwAlert
from nw.tools import NWSpellSimple
from nw.constants import nwUnicode, nwDocAction
logger = logging.getLogger(__name__)
@@ -209,7 +209,7 @@ class GuiDocEditor(QTextEdit):
risk overwriting the file if it exists. This can for instance
happen of the file contains binary elements or an encoding that
novelWriter does not support. If load is successful, or the
document is new (empty string) we set up the editor for editing
document is new (empty string), we set up the editor for editing
the file.
"""
@@ -219,6 +219,7 @@ class GuiDocEditor(QTextEdit):
self.clearEditor()
return False
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
self.hLight.setHandle(tHandle)
# Check that the document is not too big for full, initial spell
@@ -246,6 +247,7 @@ class GuiDocEditor(QTextEdit):
self.theParent.noticeBar.showNote("This document is read only.")
self.hLight.spellCheck = spTemp
qApp.restoreOverrideCursor()
return True
@@ -277,8 +279,9 @@ class GuiDocEditor(QTextEdit):
return True
def updateDocMargins(self):
"""Automatically adjust the margins so the text is centred, but
only if Config.textFixedW is enabled or we're in Zen mode.
"""Automatically adjust the margins so the text is centred if
Config.textFixedW is enabled or we're in Zen mode. Otherwise,
just ensure the margins are set correctly.
"""
if self.mainConf.textFixedW or self.theParent.isZenMode:
@@ -335,7 +338,7 @@ class GuiDocEditor(QTextEdit):
return theText
def setCursorPosition(self, thePosition):
if thePosition > 0:
if thePosition >= 0:
theCursor = self.textCursor()
theCursor.setPosition(thePosition)
self.setTextCursor(theCursor)
@@ -361,8 +364,8 @@ class GuiDocEditor(QTextEdit):
def setSpellCheck(self, theMode):
"""This is the master spell check setting function, and this one
should call all other setSpellCheck functions in other classes.
If the spell check mode is not defined, then toggle the current
status saved in the class.
If the spell check mode (theMode) is not defined (None), then
toggle the current status saved in this class.
"""
if theMode is None:
@@ -375,23 +378,29 @@ class GuiDocEditor(QTextEdit):
self.theParent.mainMenu.setSpellCheck(theMode)
self.theProject.setSpellCheck(theMode)
self.hLight.setSpellCheck(theMode)
self.reHighlightDocument()
if not self.bigDoc:
self.spellCheckDocument()
logger.verbose("Spell check is set to %s" % str(theMode))
return True
def reHighlightDocument(self):
def spellCheckDocument(self):
"""Rerun the highlighter to update spell checking status of the
currently loaded text. The fastest way to do this, at least as
of Qt 5.13, is to clear the text and put it back.
"""
logger.verbose("Running spell checker")
if self.spellCheck:
theText = self.getText()
self.clear()
bfTime = time()
self.setPlainText(theText)
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
if self.bigDoc:
theText = self.getText()
self.setPlainText(theText)
else:
self.hLight.rehighlight()
qApp.restoreOverrideCursor()
afTime = time()
logger.debug("Document re-highlighted in %.3f milliseconds" % (1000*(afTime-bfTime)))
+120 -19
View File
@@ -16,10 +16,10 @@ import nw
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QFont, QColor
from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QApplication
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QApplication, QMessageBox
)
from nw.project import NWItem
from nw.project import NWItem, NWDoc
from nw.constants import (
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert
)
@@ -171,14 +171,21 @@ class GuiDocTree(QTreeWidget):
return False
# Add the new item to the tree
nwItem = self.theProject.getItem(tHandle)
trItem = self._addTreeItem(nwItem)
self.revealTreeItem(tHandle)
self.theParent.editItem()
return True
def revealTreeItem(self, tHandle):
"""Reveal a newly added project item in the project tree.
"""
nwItem = self.theProject.getItem(tHandle)
trItem = self._addTreeItem(nwItem)
pHandle = nwItem.parHandle
if pHandle is not None and pHandle in self.theMap.keys():
self.theMap[pHandle].setExpanded(True)
self.clearSelection()
trItem.setSelected(True)
self.theParent.editItem()
return True
def moveTreeItem(self, nStep):
@@ -221,6 +228,16 @@ class GuiDocTree(QTreeWidget):
self.theProject.setTreeOrder(theList)
return True
def getTreeFromHandle(self, tHandle):
"""Recursively return all the children items starting from a
given item handle.
"""
theList = []
theItem = self._getTreeItem(tHandle)
if theItem is not None:
theList = self._scanChildren(theList, theItem, 0)
return theList
def getColumnSizes(self):
retVals = [
self.columnWidth(0),
@@ -229,7 +246,44 @@ class GuiDocTree(QTreeWidget):
]
return retVals
def deleteItem(self, tHandle=None):
def emptyTrash(self):
"""Permanently delete all documents in the Trash folder. This
function only asks for confirmation once, and calls the regular
deleteItem function for each document in the Trash folder.
"""
logger.debug("Emptying Trash folder")
if self.theProject.trashRoot is None:
self.makeAlert("There is no Trash folder.", nwAlert.INFO)
return False
theTrash = self.getTreeFromHandle(self.theProject.trashRoot)
if self.theProject.trashRoot in theTrash:
theTrash.remove(self.theProject.trashRoot)
nTrash = len(theTrash)
if nTrash == 0:
self.makeAlert("The Trash folder is empty.", nwAlert.INFO)
return False
msgBox = QMessageBox()
msgRes = msgBox.question(
self, "Empty Trash", "Permanently delete %d file%s from Trash?" % (
nTrash, "s"*int(nTrash > 1)
)
)
if msgRes != QMessageBox.Yes:
return False
logger.verbose("Deleting %d files from Trash" % nTrash)
for tHandle in self.getTreeFromHandle(self.theProject.trashRoot):
if tHandle == self.theProject.trashRoot:
continue
self.deleteItem(tHandle, True)
return True
def deleteItem(self, tHandle=None, alreadyAsked=False):
"""Delete items from the tree. Note that this does not delete
the item from the item tree in the project object. However,
since this is only meta data, there isn't really a need to do
@@ -246,21 +300,61 @@ class GuiDocTree(QTreeWidget):
trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.getItem(tHandle)
if nwItemS is None:
return False
if nwItemS.itemType == nwItemType.FILE:
logger.debug("User requested file %s moved to trash" % tHandle)
trItemP = trItemS.parent()
trItemT = self._addTrashRoot()
if trItemP is None or trItemT is None:
logger.error("Could not move item to trash")
logger.error("Could not delete item")
return False
tIndex = trItemP.indexOfChild(trItemS)
trItemC = trItemP.takeChild(tIndex)
trItemT.addChild(trItemC)
nwItemS.setParent(self.theProject.trashRoot)
self.clearSelection()
trItemP.setSelected(True)
self.theProject.setProjectChanged(True)
self.theParent.theIndex.deleteHandle(tHandle)
pHandle = nwItemS.parHandle
if pHandle is not None and pHandle == self.theProject.trashRoot:
# If the file is in the trash folder already, as the
# user if they want to permanently delete the file.
doPermanent = False
if self.mainConf.showGUI and not alreadyAsked:
msgBox = QMessageBox()
msgRes = msgBox.question(
self, "Delete File", "Permanently delete file '%s'?" % nwItemS.itemName
)
if msgRes == QMessageBox.Yes:
doPermanent = True
else:
doPermanent = True
if doPermanent:
logger.debug("Permanently deleting file with handle %s" % tHandle)
tIndex = trItemP.indexOfChild(trItemS)
trItemC = trItemP.takeChild(tIndex)
if self.theParent.docEditor.theHandle == tHandle:
self.theParent.closeDocument()
theDoc = NWDoc(self.theProject, self.theParent)
theDoc.deleteDocument(tHandle)
self.theProject.deleteItem(tHandle)
self.theParent.theIndex.deleteHandle(tHandle)
else:
# The file is not already in the trash folder, so we
# move it there.
if pHandle is None:
logger.warning("File has no parent item")
tIndex = trItemP.indexOfChild(trItemS)
trItemC = trItemP.takeChild(tIndex)
trItemT.addChild(trItemC)
nwItemS.setParent(self.theProject.trashRoot)
self.theProject.setProjectChanged(True)
self.theParent.theIndex.deleteHandle(tHandle)
elif nwItemS.itemType == nwItemType.FOLDER:
logger.debug("User requested folder %s deleted" % tHandle)
@@ -271,8 +365,6 @@ class GuiDocTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS)
if trItemS.childCount() == 0:
trItemP.takeChild(tIndex)
self.clearSelection()
trItemP.setSelected(True)
self.theProject.deleteItem(tHandle)
else:
self.makeAlert(["Cannot delete folder.","It is not empty."], nwAlert.ERROR)
@@ -428,6 +520,9 @@ class GuiDocTree(QTreeWidget):
return newItem
def _addTrashRoot(self):
"""Adds the trash root folder if it doesn't already exist in the
project tree.
"""
if self.theProject.trashRoot is None:
self.theProject.addTrash()
trItem = self._addTreeItem(
@@ -518,16 +613,22 @@ class GuiDocTree(QTreeWidget):
"""
sHandle = self.getSelectedHandle()
if sHandle is None:
logger.error("No handle selected")
return
dIndex = self.indexAt(theEvent.pos())
dIndex = self.indexAt(theEvent.pos())
if not dIndex.isValid():
logger.error("Invalid drop index")
return
dItem = self.itemFromIndex(dIndex)
dHandle = dItem.text(self.C_HANDLE)
snItem = self.theProject.getItem(sHandle)
dnItem = self.theProject.getItem(dHandle)
if dnItem is None:
self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR)
return
isSame = snItem.itemClass == dnItem.itemClass
isNone = snItem.itemClass == nwItemClass.NO_CLASS
isNote = snItem.itemLayout == nwItemLayout.NOTE
+4 -17
View File
@@ -21,7 +21,6 @@ from PyQt5.QtWidgets import (
QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem
)
from nw.tools import OptLastState
from nw.constants import nwItemLayout, nwKeyWords, nwLabels, nwFiles
logger = logging.getLogger(__name__)
@@ -75,7 +74,7 @@ class GuiProjectOutline(QWidget):
self.theParent = theParent
self.theProject = theProject
self.theIndex = self.theParent.theIndex
self.optState = OutlineLastState(self.theProject,nwFiles.OUTLINE_OPT)
self.optState = self.theProject.optState
self.showWords = True
self.showSynopsis = True
@@ -111,13 +110,13 @@ class GuiProjectOutline(QWidget):
colW.append(self.mainTree.columnWidth(iCol))
self.treeCols["width"] = colW
self.optState.setSetting("headState", self.treeCols)
self.optState.setValue("GuiProjectOutline", "headState", self.treeCols)
self.optState.saveSettings()
return
def loadHeaderState(self):
self.optState.loadSettings()
treeCols = self.optState.getSetting("headState")
treeCols = self.optState.getValue("GuiProjectOutline", "headState", {})
if "order" not in treeCols.keys(): return
if not isinstance(treeCols["order"], list): return
@@ -253,15 +252,3 @@ class GuiProjectOutline(QWidget):
return
# END Class GuiProjectOutline
class OutlineLastState(OptLastState):
def __init__(self, theProject, theFile):
OptLastState.__init__(self, theProject, theFile)
self.theState = {
"headState" : {},
}
self.dictOpt = ("headState")
return
# END Class OutlineLastState
+2 -2
View File
@@ -86,13 +86,13 @@ class GuiSearchBar(QFrame):
if not self.isVisible():
self.setVisible(True)
self.searchBox.setText(theText)
self.searchBox.setFocus(True)
self.searchBox.setFocus()
logger.verbose("Setting search text to '%s'" % theText)
return True
def setReplaceText(self, theText):
self._replaceVisible(True)
self.replaceBox.setFocus(True)
self.replaceBox.setFocus()
self.replaceBox.setText(theText)
return True
-2
View File
@@ -18,8 +18,6 @@ from PyQt5.QtWidgets import (
QWidget, QLabel, QScrollArea, QFrame, QToolButton, QCheckBox, QGridLayout
)
from nw.constants import nwLabels
logger = logging.getLogger(__name__)
class GuiDocViewDetails(QWidget):