Save project added, and a number of bits here and there.
This commit is contained in:
+1
-4
@@ -12,9 +12,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import getopt
|
import getopt
|
||||||
import gi
|
|
||||||
|
|
||||||
gi.require_version("Gtk","3.0")
|
|
||||||
|
|
||||||
from os import path, remove, rename
|
from os import path, remove, rename
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
@@ -31,7 +28,7 @@ __date__ = "2018"
|
|||||||
__maintainer__ = "Veronica Berglyd Olsen"
|
__maintainer__ = "Veronica Berglyd Olsen"
|
||||||
__email__ = "code@vkbo.net"
|
__email__ = "code@vkbo.net"
|
||||||
__status__ = "Development"
|
__status__ = "Development"
|
||||||
__website__ = "https://github.com/vkbo/novelWriter"
|
__url__ = "https://github.com/vkbo/novelWriter"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Logging
|
# Logging
|
||||||
|
|||||||
+28
-5
@@ -14,8 +14,9 @@ import logging
|
|||||||
import configparser
|
import configparser
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path, mkdir, getcwd
|
from os import path, mkdir, getcwd
|
||||||
from appdirs import user_config_dir
|
from appdirs import user_config_dir
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -29,7 +30,6 @@ class Config:
|
|||||||
# Set Application Variables
|
# Set Application Variables
|
||||||
self.appName = nw.__package__
|
self.appName = nw.__package__
|
||||||
self.appHandle = nw.__package__.lower()
|
self.appHandle = nw.__package__.lower()
|
||||||
self.appURL = "https://github.com/vkbo/novelWriter"
|
|
||||||
|
|
||||||
# Set Paths
|
# Set Paths
|
||||||
self.confPath = user_config_dir(self.appHandle)
|
self.confPath = user_config_dir(self.appHandle)
|
||||||
@@ -38,6 +38,7 @@ class Config:
|
|||||||
self.appPath = path.dirname(__file__)
|
self.appPath = path.dirname(__file__)
|
||||||
self.guiPath = path.join(self.appPath,"gui")
|
self.guiPath = path.join(self.appPath,"gui")
|
||||||
self.themePath = path.join(self.appPath,"themes")
|
self.themePath = path.join(self.appPath,"themes")
|
||||||
|
self.recentList = [""]*10
|
||||||
|
|
||||||
# If config folder does not exist, make it.
|
# If config folder does not exist, make it.
|
||||||
# This assumes that the os config folder itself exists.
|
# This assumes that the os config folder itself exists.
|
||||||
@@ -81,11 +82,18 @@ class Config:
|
|||||||
confParser.get(cnfSec,"geometry"), 2, self.winGeometry
|
confParser.get(cnfSec,"geometry"), 2, self.winGeometry
|
||||||
)
|
)
|
||||||
|
|
||||||
|
## Path
|
||||||
|
cnfSec = "Path"
|
||||||
|
if confParser.has_section(cnfSec):
|
||||||
|
for i in range(10):
|
||||||
|
if confParser.has_option(cnfSec,"recent%d" % i):
|
||||||
|
self.recentList[i] = confParser.get(cnfSec,"recent%d" % i)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def saveConfig(self):
|
def saveConfig(self):
|
||||||
|
|
||||||
logger.debug("Config: Saving")
|
logger.debug("Saving config file")
|
||||||
confParser = configparser.ConfigParser()
|
confParser = configparser.ConfigParser()
|
||||||
|
|
||||||
# Set options
|
# Set options
|
||||||
@@ -93,7 +101,14 @@ class Config:
|
|||||||
## Main
|
## Main
|
||||||
cnfSec = "Main"
|
cnfSec = "Main"
|
||||||
confParser.add_section(cnfSec)
|
confParser.add_section(cnfSec)
|
||||||
confParser.set(cnfSec,"geometry", self.packList(self.winGeometry))
|
confParser.set(cnfSec,"timestamp", datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
||||||
|
confParser.set(cnfSec,"geometry", self.packList(self.winGeometry))
|
||||||
|
|
||||||
|
## Path
|
||||||
|
cnfSec = "Path"
|
||||||
|
confParser.add_section(cnfSec)
|
||||||
|
for i in range(10):
|
||||||
|
confParser.set(cnfSec,"recent%d" % i, str(self.recentList[i]))
|
||||||
|
|
||||||
# Write config file
|
# Write config file
|
||||||
confParser.write(open(path.join(self.confPath,self.confFile),"w"))
|
confParser.write(open(path.join(self.confPath,self.confFile),"w"))
|
||||||
@@ -118,6 +133,14 @@ class Config:
|
|||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
|
|
||||||
|
def setRecent(self, recentPath):
|
||||||
|
if recentPath == "": return
|
||||||
|
if recentPath in self.recentList[0:10]:
|
||||||
|
self.recentList.remove(recentPath)
|
||||||
|
self.recentList.insert(0,recentPath)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def setConfPath(self, newPath):
|
def setConfPath(self, newPath):
|
||||||
if newPath is None: return
|
if newPath is None: return
|
||||||
if not path.isfile(newPath):
|
if not path.isfile(newPath):
|
||||||
|
|||||||
@@ -47,11 +47,20 @@ class GuiDocEditor(QWidget):
|
|||||||
self.outerBox.addWidget(self.splitEdit)
|
self.outerBox.addWidget(self.splitEdit)
|
||||||
|
|
||||||
self.guiEditor.setPlainText("Hello Kitty!")
|
self.guiEditor.setPlainText("Hello Kitty!")
|
||||||
|
self.guiEditor.setFixedWidth(600)
|
||||||
|
|
||||||
logger.debug("DocEditor initialisation complete")
|
logger.debug("DocEditor initialisation complete")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def getText(self):
|
||||||
|
|
||||||
|
theText = self.guiEditor.toHtml()
|
||||||
|
print(theText)
|
||||||
|
print(self.guiEditor.toPlainText())
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def _buildTabToolBar(self):
|
def _buildTabToolBar(self):
|
||||||
toolBar = self.editToolBar
|
toolBar = self.editToolBar
|
||||||
toolBar.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
toolBar.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||||
|
|||||||
+3
-3
@@ -46,12 +46,12 @@ class GuiDocTabs(QTabWidget):
|
|||||||
if tabType == nw.DOCTYPE_ABOUT:
|
if tabType == nw.DOCTYPE_ABOUT:
|
||||||
self._createTabAbout()
|
self._createTabAbout()
|
||||||
return True
|
return True
|
||||||
elif tabType == nw.DOCTYPE_DOC:
|
|
||||||
self._createTabDoc(theName)
|
|
||||||
return True
|
|
||||||
elif tabType == nw.DOCTYPE_PROJECT:
|
elif tabType == nw.DOCTYPE_PROJECT:
|
||||||
self._createTabProject(theName)
|
self._createTabProject(theName)
|
||||||
return True
|
return True
|
||||||
|
elif tabType == nw.DOCTYPE_DOC:
|
||||||
|
self._createTabDoc(theName)
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
+50
-10
@@ -13,13 +13,14 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from PyQt5.QtWidgets import qApp, QWidget, QMainWindow, QHBoxLayout, QVBoxLayout, QFrame, QSplitter, QAction, QToolBar
|
from PyQt5.QtWidgets import qApp, QWidget, QMainWindow, QHBoxLayout, QVBoxLayout, QFrame, QSplitter, QAction, QToolBar, QFileDialog
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt, QSize
|
||||||
from PyQt5.QtGui import QIcon, QStandardItemModel
|
from PyQt5.QtGui import QIcon, QStandardItemModel
|
||||||
|
|
||||||
from nw.gui.doctree import GuiDocTree
|
from nw.gui.doctree import GuiDocTree
|
||||||
from nw.gui.doctabs import GuiDocTabs
|
from nw.gui.doceditor import GuiDocEditor
|
||||||
|
from nw.project.project import NWProject
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -29,7 +30,8 @@ class GuiMain(QMainWindow):
|
|||||||
QWidget.__init__(self)
|
QWidget.__init__(self)
|
||||||
|
|
||||||
logger.debug("Initialising GUI ...")
|
logger.debug("Initialising GUI ...")
|
||||||
self.mainConf = nw.CONFIG
|
self.mainConf = nw.CONFIG
|
||||||
|
self.theProject = NWProject()
|
||||||
|
|
||||||
self.resize(1100,650)
|
self.resize(1100,650)
|
||||||
self.setTitle()
|
self.setTitle()
|
||||||
@@ -37,13 +39,13 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
self.statBar = self.statusBar()
|
self.statBar = self.statusBar()
|
||||||
|
|
||||||
self.docTabs = GuiDocTabs()
|
self.docEditor = GuiDocEditor()
|
||||||
|
|
||||||
self.treePane = QFrame()
|
self.treePane = QFrame()
|
||||||
self.treePane.setFrameShape(QFrame.StyledPanel)
|
self.treePane.setFrameShape(QFrame.StyledPanel)
|
||||||
self.splitMain = QSplitter(Qt.Horizontal)
|
self.splitMain = QSplitter(Qt.Horizontal)
|
||||||
self.splitMain.addWidget(self.treePane)
|
self.splitMain.addWidget(self.treePane)
|
||||||
self.splitMain.addWidget(self.docTabs)
|
self.splitMain.addWidget(self.docEditor)
|
||||||
|
|
||||||
self.treeBox = QVBoxLayout()
|
self.treeBox = QVBoxLayout()
|
||||||
self.treeView = GuiDocTree()
|
self.treeView = GuiDocTree()
|
||||||
@@ -89,6 +91,29 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def saveProject(self):
|
||||||
|
if self.theProject.projPath is None:
|
||||||
|
dlgOpt = QFileDialog.Options()
|
||||||
|
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||||
|
projPath, _ = QFileDialog.getSaveFileName(
|
||||||
|
self,"Save novelWriter Project","","novelWriter Project File (nwProject.nwx);;All Files (*)", options=dlgOpt)
|
||||||
|
if projPath:
|
||||||
|
self.theProject.setProjectPath(projPath)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
self.theProject.saveProject()
|
||||||
|
return True
|
||||||
|
|
||||||
|
#
|
||||||
|
# Document Actions
|
||||||
|
#
|
||||||
|
|
||||||
|
def saveDocument(self):
|
||||||
|
|
||||||
|
self.docEditor.getText()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
#
|
#
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
#
|
#
|
||||||
@@ -113,6 +138,7 @@ class GuiMain(QMainWindow):
|
|||||||
# File > Save Project
|
# File > Save Project
|
||||||
menuSaveProject = QAction(QIcon.fromTheme("document-save"), "Save Project", menuBar)
|
menuSaveProject = QAction(QIcon.fromTheme("document-save"), "Save Project", menuBar)
|
||||||
menuSaveProject.setStatusTip("Save Project")
|
menuSaveProject.setStatusTip("Save Project")
|
||||||
|
menuSaveProject.triggered.connect(self.saveProject)
|
||||||
fileMenu.addAction(menuSaveProject)
|
fileMenu.addAction(menuSaveProject)
|
||||||
|
|
||||||
# File > Recent Project
|
# File > Recent Project
|
||||||
@@ -147,6 +173,7 @@ class GuiMain(QMainWindow):
|
|||||||
menuSave = QAction(QIcon.fromTheme("document-save"), "&Save", menuBar)
|
menuSave = QAction(QIcon.fromTheme("document-save"), "&Save", menuBar)
|
||||||
menuSave.setShortcut("Ctrl+S")
|
menuSave.setShortcut("Ctrl+S")
|
||||||
menuSave.setStatusTip("Save document")
|
menuSave.setStatusTip("Save document")
|
||||||
|
menuSave.triggered.connect(self.saveDocument)
|
||||||
fileMenu.addAction(menuSave)
|
fileMenu.addAction(menuSave)
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
@@ -189,12 +216,17 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _closeMain(self):
|
||||||
|
logger.info("Exiting %s" % nw.__package__)
|
||||||
|
self.mainConf.saveConfig()
|
||||||
|
return
|
||||||
|
|
||||||
#
|
#
|
||||||
# Menu Action
|
# Menu Action
|
||||||
#
|
#
|
||||||
|
|
||||||
def _menuExit(self):
|
def _menuExit(self):
|
||||||
logger.info("Exiting %s" % nw.__package__)
|
self._closeMain()
|
||||||
qApp.quit()
|
qApp.quit()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -202,4 +234,12 @@ class GuiMain(QMainWindow):
|
|||||||
self.docTabs.createTab(None,nw.DOCTYPE_ABOUT)
|
self.docTabs.createTab(None,nw.DOCTYPE_ABOUT)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
#
|
||||||
|
# Events
|
||||||
|
#
|
||||||
|
|
||||||
|
def closeEvent(self, guiEvent):
|
||||||
|
self._closeMain()
|
||||||
|
guiEvent.accept()
|
||||||
|
|
||||||
# END Class GuiMain
|
# END Class GuiMain
|
||||||
|
|||||||
+21
-16
@@ -13,8 +13,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path, mkdir
|
from os import path, mkdir
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -22,13 +23,14 @@ class NWProject():
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
|
self.mainConf = nw.CONFIG
|
||||||
|
|
||||||
self.projFolder = None
|
self.projFolder = None
|
||||||
self.projTree = []
|
self.projTree = []
|
||||||
|
|
||||||
# Project Settings
|
# Project Settings
|
||||||
self.projPath = ""
|
self.projPath = None
|
||||||
self.projData = ""
|
self.projFile = "nwProject.nwx"
|
||||||
self.projName = ""
|
|
||||||
self.bookTitle = ""
|
self.bookTitle = ""
|
||||||
self.bookAuthors = []
|
self.bookAuthors = []
|
||||||
|
|
||||||
@@ -40,22 +42,19 @@ class NWProject():
|
|||||||
|
|
||||||
def saveProject(self):
|
def saveProject(self):
|
||||||
|
|
||||||
projDir = path.dirname(self.projPath)
|
if self.projPath is None:
|
||||||
projFile = path.basename(self.projPath)
|
logger.error("Project path not set, cannot save.")
|
||||||
logger.vverbose("Project folder is %s" % projDir)
|
return False
|
||||||
logger.vverbose("Project file is %s" % projFile)
|
|
||||||
|
|
||||||
if bookFile[-4:] == ".nwx":
|
if not path.isdir(self.projPath):
|
||||||
self.projData = path.join(projDir,projFile[:-4]+".nwd")
|
logger.info("Created folder %s" % self.projPath)
|
||||||
if not path.isdir(self.projData):
|
mkdir(self.projPath)
|
||||||
logger.info("Created folder %s" % self.projData)
|
|
||||||
mkdir(self.projData)
|
|
||||||
|
|
||||||
# Root element and book details
|
# Root element and book details
|
||||||
nwXML = etree.Element("novelWriterXML",attrib={
|
nwXML = etree.Element("novelWriterXML",attrib={
|
||||||
"fileVersion" : "1.0",
|
"fileVersion" : "1.0",
|
||||||
"appVersion" : str(nw.__version__),
|
"appVersion" : str(nw.__version__),
|
||||||
"timeStamp" : getTimeStamp("-"),
|
"timeStamp" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
})
|
})
|
||||||
xBook = etree.SubElement(nwXML,"book")
|
xBook = etree.SubElement(nwXML,"book")
|
||||||
xBookTitle = etree.SubElement(xBook,"title")
|
xBookTitle = etree.SubElement(xBook,"title")
|
||||||
@@ -66,7 +65,7 @@ class NWProject():
|
|||||||
xBookAuthor.text = bookAuthor
|
xBookAuthor.text = bookAuthor
|
||||||
|
|
||||||
# Write the xml tree to file
|
# Write the xml tree to file
|
||||||
with open(self.bookPath,"wb") as outFile:
|
with open(path.join(self.projPath,self.projFile),"wb") as outFile:
|
||||||
outFile.write(etree.tostring(
|
outFile.write(etree.tostring(
|
||||||
nwXML,
|
nwXML,
|
||||||
pretty_print = True,
|
pretty_print = True,
|
||||||
@@ -74,12 +73,18 @@ class NWProject():
|
|||||||
xml_declaration = True
|
xml_declaration = True
|
||||||
))
|
))
|
||||||
|
|
||||||
|
self.mainConf.setRecent(self.projPath)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
#
|
#
|
||||||
# Set Functions
|
# Set Functions
|
||||||
#
|
#
|
||||||
|
|
||||||
|
def setProjectPath(self, projPath):
|
||||||
|
self.projPath = projPath
|
||||||
|
return True
|
||||||
|
|
||||||
def setProjectName(self, projName):
|
def setProjectName(self, projName):
|
||||||
self.projName = projName.strip()
|
self.projName = projName.strip()
|
||||||
return True
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user