@@ -47,6 +47,7 @@ class Config:
|
|||||||
self.confPath = None
|
self.confPath = None
|
||||||
self.confFile = None
|
self.confFile = None
|
||||||
self.homePath = None
|
self.homePath = None
|
||||||
|
self.lastPath = None
|
||||||
self.appPath = None
|
self.appPath = None
|
||||||
self.appRoot = None
|
self.appRoot = None
|
||||||
self.appIcon = None
|
self.appIcon = None
|
||||||
@@ -129,6 +130,7 @@ class Config:
|
|||||||
|
|
||||||
self.confFile = self.appHandle+".conf"
|
self.confFile = self.appHandle+".conf"
|
||||||
self.homePath = path.expanduser("~")
|
self.homePath = path.expanduser("~")
|
||||||
|
self.lastPath = self.homePath
|
||||||
self.appPath = path.dirname(__file__)
|
self.appPath = path.dirname(__file__)
|
||||||
self.appRoot = path.join(self.appPath,path.pardir)
|
self.appRoot = path.join(self.appPath,path.pardir)
|
||||||
self.helpPath = path.join(self.appRoot,"help","en_GB")
|
self.helpPath = path.join(self.appRoot,"help","en_GB")
|
||||||
@@ -212,6 +214,7 @@ class Config:
|
|||||||
|
|
||||||
## Path
|
## Path
|
||||||
cnfSec = "Path"
|
cnfSec = "Path"
|
||||||
|
self.lastPath = self._parseLine(cnfParse, cnfSec, "lastpath", self.CNF_STR, self.lastPath)
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
self.recentList[i] = self._parseLine(cnfParse, cnfSec, "recent%d" % i,self.CNF_STR, self.recentList[i])
|
self.recentList[i] = self._parseLine(cnfParse, cnfSec, "recent%d" % i,self.CNF_STR, self.recentList[i])
|
||||||
|
|
||||||
@@ -278,6 +281,7 @@ class Config:
|
|||||||
## Path
|
## Path
|
||||||
cnfSec = "Path"
|
cnfSec = "Path"
|
||||||
cnfParse.add_section(cnfSec)
|
cnfParse.add_section(cnfSec)
|
||||||
|
cnfParse.set(cnfSec,"lastpath", str(self.lastPath))
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
cnfParse.set(cnfSec,"recent%d" % i, str(self.recentList[i]))
|
cnfParse.set(cnfSec,"recent%d" % i, str(self.recentList[i]))
|
||||||
|
|
||||||
@@ -312,6 +316,13 @@ class Config:
|
|||||||
self.confFile = path.basename(newPath)
|
self.confFile = path.basename(newPath)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def setLastPath(self, lastPath):
|
||||||
|
if lastPath is None or lastPath == "":
|
||||||
|
self.lastPath = ""
|
||||||
|
else:
|
||||||
|
self.lastPath = path.dirname(lastPath)
|
||||||
|
return True
|
||||||
|
|
||||||
def setWinSize(self, newWidth, newHeight):
|
def setWinSize(self, newWidth, newHeight):
|
||||||
if abs(self.winGeometry[0] - newWidth) > 5:
|
if abs(self.winGeometry[0] - newWidth) > 5:
|
||||||
self.winGeometry[0] = newWidth
|
self.winGeometry[0] = newWidth
|
||||||
|
|||||||
+1
-1
@@ -61,7 +61,7 @@ class nwLabels():
|
|||||||
nwItemLayout.BOOK : "Book",
|
nwItemLayout.BOOK : "Book",
|
||||||
nwItemLayout.PAGE : "Plain Page",
|
nwItemLayout.PAGE : "Plain Page",
|
||||||
nwItemLayout.PARTITION : "Partition",
|
nwItemLayout.PARTITION : "Partition",
|
||||||
nwItemLayout.UNNUMBERED : "Un-Numbered",
|
nwItemLayout.UNNUMBERED : "Unnumbered",
|
||||||
nwItemLayout.CHAPTER : "Chapter",
|
nwItemLayout.CHAPTER : "Chapter",
|
||||||
nwItemLayout.SCENE : "Scene",
|
nwItemLayout.SCENE : "Scene",
|
||||||
nwItemLayout.NOTE : "Note",
|
nwItemLayout.NOTE : "Note",
|
||||||
|
|||||||
@@ -289,6 +289,9 @@ class GuiDocEditor(QTextEdit):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def isEmpty(self):
|
||||||
|
return self.qDocument.isEmpty()
|
||||||
|
|
||||||
##
|
##
|
||||||
# Document Events and Maintenance
|
# Document Events and Maintenance
|
||||||
##
|
##
|
||||||
|
|||||||
+13
-4
@@ -98,8 +98,16 @@ class GuiDocTree(QTreeWidget):
|
|||||||
|
|
||||||
if itemClass is None and pHandle is not None:
|
if itemClass is None and pHandle is not None:
|
||||||
itemClass = self.theProject.getItem(pHandle).itemClass
|
itemClass = self.theProject.getItem(pHandle).itemClass
|
||||||
|
|
||||||
if itemClass is None:
|
if itemClass is None:
|
||||||
self.makeAlert("Failed to find an appropriate item class for item %s" % pHandle, nwAlert.BUG)
|
if itemType is not None:
|
||||||
|
if itemType == nwItemType.FILE:
|
||||||
|
self.makeAlert("Please select a location in the tree to add a document.", nwAlert.ERROR)
|
||||||
|
return False
|
||||||
|
elif itemType == nwItemType.FOLDER:
|
||||||
|
self.makeAlert("Please select a location in the tree to add a folder.", nwAlert.ERROR)
|
||||||
|
return False
|
||||||
|
self.makeAlert("Failed to add new item.", nwAlert.BUG)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.verbose("Adding new item of type %s and class %s to handle %s" % (
|
logger.verbose("Adding new item of type %s and class %s to handle %s" % (
|
||||||
@@ -418,9 +426,10 @@ class GuiDocTree(QTreeWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _cleanOrphanedRoot(self):
|
def _cleanOrphanedRoot(self):
|
||||||
if self.orphRoot.childCount() == 0:
|
if self.orphRoot is not None:
|
||||||
self.takeTopLevelItem(self.indexOfTopLevelItem(self.orphRoot))
|
if self.orphRoot.childCount() == 0:
|
||||||
self.orphRoot = None
|
self.takeTopLevelItem(self.indexOfTopLevelItem(self.orphRoot))
|
||||||
|
self.orphRoot = None
|
||||||
return
|
return
|
||||||
|
|
||||||
def _updateItemParent(self, tHandle):
|
def _updateItemParent(self, tHandle):
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class GuiItemEditor(QDialog):
|
|||||||
if itemLayout in self.validLayouts:
|
if itemLayout in self.validLayouts:
|
||||||
self.editLayout.addItem(nwLabels.LAYOUT_NAME[itemLayout],itemLayout)
|
self.editLayout.addItem(nwLabels.LAYOUT_NAME[itemLayout],itemLayout)
|
||||||
|
|
||||||
self.mainForm.addRow("Name", self.editName)
|
self.mainForm.addRow("Label", self.editName)
|
||||||
self.mainForm.addRow("Status", self.editStatus)
|
self.mainForm.addRow("Status", self.editStatus)
|
||||||
self.mainForm.addRow("Layout", self.editLayout)
|
self.mainForm.addRow("Layout", self.editLayout)
|
||||||
|
|
||||||
|
|||||||
+9
-2
@@ -312,8 +312,15 @@ class GuiMainMenu(QMenuBar):
|
|||||||
menuItem.triggered.connect(self.theParent.closeDocViewer)
|
menuItem.triggered.connect(self.theParent.closeDocViewer)
|
||||||
self.docuMenu.addAction(menuItem)
|
self.docuMenu.addAction(menuItem)
|
||||||
|
|
||||||
# # Document > Separator
|
# Document > Separator
|
||||||
# self.docuMenu.addSeparator()
|
self.docuMenu.addSeparator()
|
||||||
|
|
||||||
|
# Document > Close Preview
|
||||||
|
menuItem = QAction("Import from File", self)
|
||||||
|
menuItem.setStatusTip("Import document from a text or markdown file")
|
||||||
|
menuItem.setShortcut("Ctrl+Shift+I")
|
||||||
|
menuItem.triggered.connect(self.theParent.importDocument)
|
||||||
|
self.docuMenu.addAction(menuItem)
|
||||||
|
|
||||||
# # Document > Split
|
# # Document > Split
|
||||||
# menuItem = QAction("Split Document", self)
|
# menuItem = QAction("Split Document", self)
|
||||||
|
|||||||
@@ -366,6 +366,54 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def importDocument(self):
|
||||||
|
|
||||||
|
lastPath = self.mainConf.lastPath
|
||||||
|
|
||||||
|
extFilter = [
|
||||||
|
"Text files (*.txt)",
|
||||||
|
"Markdown files (*.md)",
|
||||||
|
"All files (*.*)",
|
||||||
|
]
|
||||||
|
dlgOpt = QFileDialog.Options()
|
||||||
|
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||||
|
inPath = QFileDialog.getOpenFileName(
|
||||||
|
self,"Import File",lastPath,options=dlgOpt,filter=";;".join(extFilter)
|
||||||
|
)
|
||||||
|
if inPath:
|
||||||
|
loadFile = inPath[0]
|
||||||
|
self.mainConf.setLastPath(loadFile)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
theText = None
|
||||||
|
try:
|
||||||
|
with open(loadFile,mode="rt") as inFile:
|
||||||
|
theText = inFile.read()
|
||||||
|
except Exception as e:
|
||||||
|
self.makeAlert(["Could not read file. The file cannot be a binary file.",str(e)], nwAlert.ERROR)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if self.docEditor.theHandle is None:
|
||||||
|
self.makeAlert(["Please open a document to import the text file into."], nwAlert.ERROR)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.docEditor.isEmpty():
|
||||||
|
if self.mainConf.showGUI:
|
||||||
|
msgBox = QMessageBox()
|
||||||
|
msgRes = msgBox.question(
|
||||||
|
self, "Import Document",
|
||||||
|
"Importing the file will overwrite the current content of the document. Do you want to proceed?"
|
||||||
|
)
|
||||||
|
if msgRes != QMessageBox.Yes:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.docEditor.setText(theText)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
# Tree Item Actions
|
# Tree Item Actions
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
## Interlude
|
||||||
|
|
||||||
|
I am the very model of a modern Major-General
|
||||||
|
I've information vegetable, animal, and mineral
|
||||||
|
I know the kings of England, and I quote the fights historical
|
||||||
|
From Marathon to Waterloo, in order categorical
|
||||||
|
|
||||||
|
I'm very well acquainted, too, with matters mathematical
|
||||||
|
I understand equations, both the simple and quadratical
|
||||||
|
About binomial theorem I'm teeming with a lot o’ news
|
||||||
|
With many cheerful facts about the square of the hypotenuse
|
||||||
|
|
||||||
|
With many cheerful facts about the square of the hypotenuse
|
||||||
|
With many cheerful facts about the square of the hypotenuse
|
||||||
|
With many cheerful facts about the square of the hypotepotenuse
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.3.1" fileVersion="1.0" timeStamp="2019-10-21 20:54:53">
|
<novelWriterXML appVersion="0.3.1" fileVersion="1.0" timeStamp="2019-10-23 21:21:02">
|
||||||
<project>
|
<project>
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<title>Sample Project</title>
|
<title>Sample Project</title>
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
</project>
|
</project>
|
||||||
<settings>
|
<settings>
|
||||||
<spellCheck>True</spellCheck>
|
<spellCheck>True</spellCheck>
|
||||||
<lastEdited>636b6aa9b697b</lastEdited>
|
<lastEdited>ba8a28a246524</lastEdited>
|
||||||
<lastViewed>636b6aa9b697b</lastViewed>
|
<lastViewed>636b6aa9b697b</lastViewed>
|
||||||
<lastWordCount>758</lastWordCount>
|
<lastWordCount>859</lastWordCount>
|
||||||
<autoReplace>
|
<autoReplace>
|
||||||
<A>B</A>
|
<A>B</A>
|
||||||
<B>E</B>
|
<B>E</B>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<entry blue="175" green="0" red="117">Main</entry>
|
<entry blue="175" green="0" red="117">Main</entry>
|
||||||
</importance>
|
</importance>
|
||||||
</settings>
|
</settings>
|
||||||
<content count="18">
|
<content count="19">
|
||||||
<item handle="7031beac91f75" order="0" parent="None">
|
<item handle="7031beac91f75" order="0" parent="None">
|
||||||
<name>Novel</name>
|
<name>Novel</name>
|
||||||
<type>ROOT</type>
|
<type>ROOT</type>
|
||||||
@@ -96,7 +96,19 @@
|
|||||||
<paraCount>2</paraCount>
|
<paraCount>2</paraCount>
|
||||||
<cursorPos>448</cursorPos>
|
<cursorPos>448</cursorPos>
|
||||||
</item>
|
</item>
|
||||||
<item handle="96b68994dfa3d" order="3" parent="e7ded148d6e4a">
|
<item handle="ba8a28a246524" order="3" parent="e7ded148d6e4a">
|
||||||
|
<name>Interlude</name>
|
||||||
|
<type>FILE</type>
|
||||||
|
<class>NOVEL</class>
|
||||||
|
<status>Finished</status>
|
||||||
|
<expanded>False</expanded>
|
||||||
|
<layout>UNNUMBERED</layout>
|
||||||
|
<charCount>614</charCount>
|
||||||
|
<wordCount>101</wordCount>
|
||||||
|
<paraCount>3</paraCount>
|
||||||
|
<cursorPos>633</cursorPos>
|
||||||
|
</item>
|
||||||
|
<item handle="96b68994dfa3d" order="4" parent="e7ded148d6e4a">
|
||||||
<name>A Note on Ipsums</name>
|
<name>A Note on Ipsums</name>
|
||||||
<type>FILE</type>
|
<type>FILE</type>
|
||||||
<class>NOVEL</class>
|
<class>NOVEL</class>
|
||||||
@@ -108,7 +120,7 @@
|
|||||||
<paraCount>5</paraCount>
|
<paraCount>5</paraCount>
|
||||||
<cursorPos>0</cursorPos>
|
<cursorPos>0</cursorPos>
|
||||||
</item>
|
</item>
|
||||||
<item handle="88706ddc78b1b" order="4" parent="e7ded148d6e4a">
|
<item handle="88706ddc78b1b" order="5" parent="e7ded148d6e4a">
|
||||||
<name>Chapter Two</name>
|
<name>Chapter Two</name>
|
||||||
<type>FILE</type>
|
<type>FILE</type>
|
||||||
<class>NOVEL</class>
|
<class>NOVEL</class>
|
||||||
@@ -120,7 +132,7 @@
|
|||||||
<paraCount>0</paraCount>
|
<paraCount>0</paraCount>
|
||||||
<cursorPos>76</cursorPos>
|
<cursorPos>76</cursorPos>
|
||||||
</item>
|
</item>
|
||||||
<item handle="ae7339df26ded" order="5" parent="e7ded148d6e4a">
|
<item handle="ae7339df26ded" order="6" parent="e7ded148d6e4a">
|
||||||
<name>We Found John!</name>
|
<name>We Found John!</name>
|
||||||
<type>FILE</type>
|
<type>FILE</type>
|
||||||
<class>NOVEL</class>
|
<class>NOVEL</class>
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ backuponclose = False
|
|||||||
askbeforebackup = True
|
askbeforebackup = True
|
||||||
|
|
||||||
[Path]
|
[Path]
|
||||||
|
lastpath =
|
||||||
recent0 =
|
recent0 =
|
||||||
recent1 =
|
recent1 =
|
||||||
recent2 =
|
recent2 =
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ def testConfigInit(nwTemp,nwRef):
|
|||||||
tmpConf = path.join(nwTemp,"novelwriter.conf")
|
tmpConf = path.join(nwTemp,"novelwriter.conf")
|
||||||
refConf = path.join(nwRef, "novelwriter.conf")
|
refConf = path.join(nwRef, "novelwriter.conf")
|
||||||
assert theConf.initConfig(nwTemp)
|
assert theConf.initConfig(nwTemp)
|
||||||
|
assert theConf.setLastPath("")
|
||||||
|
assert theConf.saveConfig()
|
||||||
assert cmpFiles(tmpConf, refConf, [2])
|
assert cmpFiles(tmpConf, refConf, [2])
|
||||||
assert not theConf.confChanged
|
assert not theConf.confChanged
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user