diff --git a/nw/assets/icons/fallback/proj_nwx.svg b/nw/assets/icons/fallback/proj_nwx.svg
new file mode 100644
index 00000000..6495b39c
--- /dev/null
+++ b/nw/assets/icons/fallback/proj_nwx.svg
@@ -0,0 +1,252 @@
+
+
diff --git a/nw/gui/dialogs/configeditor.py b/nw/gui/dialogs/configeditor.py
index 4108cbcc..77abc231 100644
--- a/nw/gui/dialogs/configeditor.py
+++ b/nw/gui/dialogs/configeditor.py
@@ -64,7 +64,7 @@ class GuiConfigEditor(PagedDialog):
self.addTab(self.tabGeneral, "General")
self.addTab(self.tabLayout, "Layout")
- self.addTab(self.tabEditing, "Editing")
+ self.addTab(self.tabEditing, "Editor")
self.addTab(self.tabAutoRep, "Auto-Replace")
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
@@ -174,22 +174,6 @@ class GuiConfigEditGeneralTab(QWidget):
"Changing this requires restarting %s." % nw.__package__
)
- ## Syntax Highlighting
- self.selectSyntax = QComboBox()
- self.selectSyntax.setMinimumWidth(200)
- self.theSyntaxes = self.theTheme.listSyntax()
- for syntaxFile, syntaxName in self.theSyntaxes:
- self.selectSyntax.addItem(syntaxName, syntaxFile)
- syntaxIdx = self.selectSyntax.findData(self.mainConf.guiSyntax)
- if syntaxIdx != -1:
- self.selectSyntax.setCurrentIndex(syntaxIdx)
-
- self.mainForm.addRow(
- "Syntax highlight theme",
- self.selectSyntax,
- ""
- )
-
## Dark Icons
self.preferDarkIcons = QSwitch()
self.preferDarkIcons.setChecked(self.mainConf.guiDark)
@@ -210,13 +194,6 @@ class GuiConfigEditGeneralTab(QWidget):
self.showFullPath
)
- self.highlightQuotes = QSwitch()
- self.highlightQuotes.setChecked(self.mainConf.highlightQuotes)
- self.mainForm.addRow(
- "Add highlighting to text in quotes",
- self.highlightQuotes
- )
-
# AutoSave Settings
# =================
self.mainForm.addGroupLabel("Automatic Save")
@@ -287,11 +264,9 @@ class GuiConfigEditGeneralTab(QWidget):
needsRestart = False
guiTheme = self.selectTheme.currentData()
- guiSyntax = self.selectSyntax.currentData()
guiIcons = self.selectIcons.currentData()
guiDark = self.preferDarkIcons.isChecked()
showFullPath = self.showFullPath.isChecked()
- highlightQuotes = self.highlightQuotes.isChecked()
autoSaveDoc = self.autoSaveDoc.value()
autoSaveProj = self.autoSaveProj.value()
backupPath = self.backupPath
@@ -303,11 +278,9 @@ class GuiConfigEditGeneralTab(QWidget):
needsRestart |= self.mainConf.guiIcons != guiIcons
self.mainConf.guiTheme = guiTheme
- self.mainConf.guiSyntax = guiSyntax
self.mainConf.guiIcons = guiIcons
self.mainConf.guiDark = guiDark
self.mainConf.showFullPath = showFullPath
- self.mainConf.highlightQuotes = highlightQuotes
self.mainConf.autoSaveDoc = autoSaveDoc
self.mainConf.autoSaveProj = autoSaveProj
self.mainConf.backupPath = backupPath
@@ -530,6 +503,33 @@ class GuiConfigEditEditingTab(QWidget):
self.mainForm.setHelpTextStyle(self.theTheme.helpText)
self.setLayout(self.mainForm)
+ # Spell Checking
+ # ==============
+ self.mainForm.addGroupLabel("Syntax Highlighting")
+
+ ## Syntax Highlighting
+ self.selectSyntax = QComboBox()
+ self.selectSyntax.setMinimumWidth(200)
+ self.theSyntaxes = self.theTheme.listSyntax()
+ for syntaxFile, syntaxName in self.theSyntaxes:
+ self.selectSyntax.addItem(syntaxName, syntaxFile)
+ syntaxIdx = self.selectSyntax.findData(self.mainConf.guiSyntax)
+ if syntaxIdx != -1:
+ self.selectSyntax.setCurrentIndex(syntaxIdx)
+
+ self.mainForm.addRow(
+ "Highlight theme",
+ self.selectSyntax,
+ ""
+ )
+
+ self.highlightQuotes = QSwitch()
+ self.highlightQuotes.setChecked(self.mainConf.highlightQuotes)
+ self.mainForm.addRow(
+ "Highlight text wrapped in quotes",
+ self.highlightQuotes
+ )
+
# Spell Checking
# ==============
self.mainForm.addGroupLabel("Spell Checking")
@@ -583,13 +583,17 @@ class GuiConfigEditEditingTab(QWidget):
validEntries = True
needsRestart = False
- spellTool = self.spellToolList.currentData()
- spellLanguage = self.spellLangList.currentData()
- bigDocLimit = self.bigDocLimit.value()
+ guiSyntax = self.selectSyntax.currentData()
+ highlightQuotes = self.highlightQuotes.isChecked()
+ spellTool = self.spellToolList.currentData()
+ spellLanguage = self.spellLangList.currentData()
+ bigDocLimit = self.bigDocLimit.value()
- self.mainConf.spellTool = spellTool
- self.mainConf.spellLanguage = spellLanguage
- self.mainConf.bigDocLimit = bigDocLimit
+ self.mainConf.guiSyntax = guiSyntax
+ self.mainConf.highlightQuotes = highlightQuotes
+ self.mainConf.spellTool = spellTool
+ self.mainConf.spellLanguage = spellLanguage
+ self.mainConf.bigDocLimit = bigDocLimit
self.mainConf.confChanged = True
diff --git a/nw/gui/dialogs/projectload.py b/nw/gui/dialogs/projectload.py
index 1ae20b64..46d48824 100644
--- a/nw/gui/dialogs/projectload.py
+++ b/nw/gui/dialogs/projectload.py
@@ -33,7 +33,7 @@ from datetime import datetime
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QTreeWidget,
- QAbstractItemView, QTreeWidgetItem
+ QAbstractItemView, QTreeWidgetItem, QDialogButtonBox, QLabel
)
from nw.common import formatInt
@@ -42,25 +42,33 @@ logger = logging.getLogger(__name__)
class GuiProjectLoad(QDialog):
+ NONE_STATE = 0
+ BROWSE_STATE = 1
+ NEW_STATE = 2
+ OPEN_STATE = 3
+
def __init__(self, theParent):
QDialog.__init__(self, theParent)
logger.debug("Initialising GuiProjectLoad ...")
- self.mainConf = nw.CONFIG
- self.theParent = theParent
- self.sourceItem = None
- self.openPath = None
+ self.mainConf = nw.CONFIG
+ self.theParent = theParent
+ self.openState = self.NONE_STATE
+ self.openPath = None
+
+ self.outerBox = QVBoxLayout()
+ self.innerBox = QHBoxLayout()
+ self.outerBox.setSpacing(16)
+ self.innerBox.setSpacing(16)
- self.outerBox = QHBoxLayout()
- self.innerBox = QVBoxLayout()
self.setWindowTitle("Open Project")
- self.setLayout(self.outerBox)
+ self.setMinimumWidth(650)
+ self.setMinimumHeight(400)
+ self.setModal(True)
- self.guiDeco = self.theParent.theTheme.loadDecoration("nwicon", (128, 128))
-
- self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
- self.outerBox.addLayout(self.innerBox)
+ self.guiDeco = self.theParent.theTheme.loadDecoration("nwicon", (96, 96))
+ self.innerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
self.projectForm = QGridLayout()
self.projectForm.setContentsMargins(0, 0, 0, 0)
@@ -71,34 +79,45 @@ class GuiProjectLoad(QDialog):
self.listBox.setColumnCount(4)
self.listBox.setHeaderLabels(["Working Title","Words","Last Opened","Path"])
self.listBox.setRootIsDecorated(False)
+ self.listBox.setColumnHidden(3, True)
+ self.listBox.itemClicked.connect(self._doSelectRecent)
self.listBox.itemDoubleClicked.connect(self._doOpenRecent)
treeHead = self.listBox.headerItem()
treeHead.setTextAlignment(1, Qt.AlignRight)
treeHead.setTextAlignment(2, Qt.AlignRight)
- self.recentButton = QPushButton("Open")
- self.recentButton.clicked.connect(self._doOpenRecent)
- self.browseButton = QPushButton("Browse")
- self.browseButton.clicked.connect(self._doBrowse)
- self.closeButton = QPushButton("Close")
- self.closeButton.clicked.connect(self._doClose)
+ self.lblRecent = QLabel("Recently Opened:")
+ self.lblPath = QLabel("Path:")
+ self.selPath = QLabel("")
+ self.selPath.setWordWrap(True)
- self.projectForm.addWidget(self.listBox, 0, 0, 1, 4)
- self.projectForm.addWidget(self.recentButton, 1, 1)
- self.projectForm.addWidget(self.browseButton, 1, 2)
- self.projectForm.addWidget(self.closeButton, 1, 3)
- self.projectForm.setColumnStretch(0, 1)
+ self.projectForm.addWidget(self.lblRecent, 0, 0, 1, 2)
+ self.projectForm.addWidget(self.listBox, 1, 0, 1, 2)
+ self.projectForm.addWidget(self.lblPath, 2, 0, 1, 1, Qt.AlignTop)
+ self.projectForm.addWidget(self.selPath, 2, 1, 1, 1, Qt.AlignTop)
+ self.projectForm.setColumnStretch(1, 1)
+ self.projectForm.setVerticalSpacing(4)
+ self.projectForm.setHorizontalSpacing(8)
self.innerBox.addLayout(self.projectForm)
- self.rejected.connect(self._doClose)
- self.setModal(True)
- self.setMinimumWidth(750)
- self.setMinimumHeight(450)
- self.show()
+ self.buttonBox = QDialogButtonBox(QDialogButtonBox.Open | QDialogButtonBox.Cancel)
+ self.buttonBox.accepted.connect(self._doOpenRecent)
+ self.buttonBox.rejected.connect(self._doClose)
+
+ self.newButton = self.buttonBox.addButton("New", QDialogButtonBox.ActionRole)
+ self.newButton.clicked.connect(self._doNewProject)
+
+ self.browseButton = self.buttonBox.addButton("Browse", QDialogButtonBox.ActionRole)
+ self.browseButton.clicked.connect(self._doBrowse)
+
+ self.outerBox.addLayout(self.innerBox)
+ self.outerBox.addWidget(self.buttonBox)
+ self.setLayout(self.outerBox)
self._populateList()
+ self._doSelectRecent()
logger.debug("GuiProjectLoad initialisation complete")
@@ -116,10 +135,19 @@ class GuiProjectLoad(QDialog):
selItems = self.listBox.selectedItems()
if selItems:
self.openPath = selItems[0].text(3)
+ self.openState = self.OPEN_STATE
self.accept()
else:
self.openPath = None
+ self.openState = self.NONE_STATE
+ return
+ def _doSelectRecent(self):
+ """A recent item has been selected.
+ """
+ selList = self.listBox.selectedItems()
+ if selList:
+ self.selPath.setText(selList[0].text(3))
return
def _doBrowse(self):
@@ -129,6 +157,7 @@ class GuiProjectLoad(QDialog):
logger.verbose("GuiProjectLoad browse button clicked")
self._saveDialogState()
self.openPath = None
+ self.openState = self.BROWSE_STATE
self.accept()
return
@@ -140,6 +169,16 @@ class GuiProjectLoad(QDialog):
self.close()
return
+ def _doNewProject(self):
+ """Create a new project.
+ """
+ logger.verbose("GuiProjectLoad new project button clicked")
+ self._saveDialogState()
+ self.openPath = None
+ self.openState = self.NEW_STATE
+ self.accept()
+ return
+
##
# Internal Functions
##
@@ -156,7 +195,6 @@ class GuiProjectLoad(QDialog):
def _populateList(self):
"""Populate the list box with recent project data.
"""
-
listOrder = []
listData = {}
for projPath in self.mainConf.recentProj.keys():
@@ -178,6 +216,7 @@ class GuiProjectLoad(QDialog):
hasSelection = False
for timeStamp in sorted(listOrder, reverse=True):
newItem = QTreeWidgetItem([""]*4)
+ newItem.setIcon(0, self.theParent.theTheme.getIcon("proj_nwx"))
newItem.setText(0, listData[timeStamp][0])
newItem.setText(1, formatInt(listData[timeStamp][1]))
newItem.setText(2, datetime.fromtimestamp(timeStamp).strftime("%x %X"))
diff --git a/nw/gui/icons.py b/nw/gui/icons.py
index fe596fe3..a57f3029 100644
--- a/nw/gui/icons.py
+++ b/nw/gui/icons.py
@@ -76,6 +76,7 @@ class GuiIcons:
"cls_trash" : (QStyle.SP_DriveHDIcon, "drive-harddisk"),
"proj_document" : (QStyle.SP_FileIcon, "x-office-document"),
"proj_folder" : (QStyle.SP_DirIcon, "folder"),
+ "proj_nwx" : (None, None),
"status_lang" : (None, None),
"status_time" : (None, None),
"status_stats" : (None, None),
@@ -295,8 +296,10 @@ class GuiIcons:
# Finally. we check if we have a fallback icon
if self.mainConf.guiDark:
fbackIcon = path.join(self.mainConf.iconPath, self.fbackName, "%s-dark.svg" % iconKey)
- else:
- fbackIcon = path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey)
+ if path.isfile(fbackIcon):
+ logger.verbose("Loading icon '%s' from fallback theme" % iconKey)
+ return QIcon(fbackIcon)
+ fbackIcon = path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey)
if path.isfile(fbackIcon):
logger.verbose("Loading icon '%s' from fallback theme" % iconKey)
return QIcon(fbackIcon)
diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py
index 6d104357..0d2643c6 100644
--- a/nw/gui/statusbar.py
+++ b/nw/gui/statusbar.py
@@ -212,7 +212,7 @@ class GuiMainStatus(QStatusBar):
sWC = self.sessWords,
))
self.statsText.setText((
- "D:{wC:n} P:{pWC:n} S:{sWC:n}"
+ "D:{wC:n} P:{pWC:n} ({sWC:+n})"
).format(
wC = self.wordCount,
pWC = self.projWords,
@@ -243,10 +243,10 @@ class StatusLED(QAbstractButton):
def __init__(self, colNone, colTrue, colFalse, sW, sH, parent=None):
super().__init__(parent=parent)
- self.colNone = colNone
- self.colTrue = colTrue
- self.colFalse = colFalse
- self._theCol = colNone
+ self.colNone = colNone
+ self.colTrue = colTrue
+ self.colFalse = colFalse
+ self._theCol = colNone
self.setFixedWidth(sW)
self.setFixedHeight(sH)
diff --git a/nw/guimain.py b/nw/guimain.py
index e8c0840a..558712ed 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -262,7 +262,12 @@ class GuiMain(QMainWindow):
dlgProj = GuiProjectLoad(self)
dlgProj.exec_()
if dlgProj.result() == QDialog.Accepted:
- self.openProject(dlgProj.openPath)
+ if dlgProj.openState == GuiProjectLoad.OPEN_STATE:
+ self.openProject(dlgProj.openPath)
+ elif dlgProj.openState == GuiProjectLoad.BROWSE_STATE:
+ self.openProject(dlgProj.openPath)
+ elif dlgProj.openState == GuiProjectLoad.NEW_STATE:
+ self.newProject()
return True