From 5d7dfd3cea3fddfb28426c72a37669384c138860 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 15 May 2020 23:40:20 +0200
Subject: [PATCH 1/9] Moved some package checks into the main function so we
can pop an error dialog for non-command line users.
---
nw/__init__.py | 39 ++++++++++++++++++++++++++++++++++++++-
nw/config.py | 1 +
2 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/nw/__init__.py b/nw/__init__.py
index 31c19ee5..8010c267 100644
--- a/nw/__init__.py
+++ b/nw/__init__.py
@@ -32,7 +32,7 @@ import logging
from os import path, remove, rename
from PyQt5.QtGui import QIcon
-from PyQt5.QtWidgets import QApplication
+from PyQt5.QtWidgets import QApplication, QErrorMessage
from nw.guimain import GuiMain
from nw.config import Config
@@ -217,6 +217,43 @@ def main(sysArgs=None):
logger.setLevel(debugLevel)
+ # Check Packages and Versions
+ errorData = []
+ if sys.hexversion < 0x030600F0:
+ errorData.append(
+ "At least Python 3.6 is required."
+ )
+ if CONFIG.verQtValue < 50200:
+ errorData.append(
+ "At least Qt5 version 5.2 is required, found %s." % CONFIG.verQtString
+ )
+ if CONFIG.verPyQtValue < 50200:
+ errorData.append(
+ "At least PyQt5 version 5.2 is required, found %s." % CONFIG.verPyQtString
+ )
+ try:
+ import PyQt5.QtSvg
+ except:
+ errorData.append("Python module 'PyQt5.QtSvg' is missing.")
+ try:
+ import lxml
+ except:
+ errorData.append("Python module 'lxml' is missing.")
+
+ if errorData:
+ errApp = QApplication([])
+ errMsg = QErrorMessage()
+ errMsg.setMinimumWidth(500)
+ errMsg.setMinimumHeight(300)
+ errMsg.showMessage((
+ "ERROR: %s cannot start due to the following issues:
"
+ " - %s
Exiting."
+ ) % (
+ __package__, "
- ".join(errorData)
+ ))
+ errApp.exec_()
+ sys.exit(1)
+
CONFIG.initConfig(confPath, dataPath)
if testMode:
diff --git a/nw/config.py b/nw/config.py
index 985f4b8d..7bc3bf77 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -36,6 +36,7 @@ from time import time
from PyQt5.Qt import PYQT_VERSION_STR
from PyQt5.QtCore import QT_VERSION_STR, QStandardPaths, QSysInfo
+from PyQt5.QtWidgets import QErrorMessage
from nw.constants import nwFiles, nwUnicode
from nw.common import splitVersionNumber, formatTimeStamp
From 752ec8a52bd418690ae0d361275a218541b7cbe1 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 15 May 2020 23:43:32 +0200
Subject: [PATCH 2/9] Clean up the launcher script, and some other bits.
---
novelWriter.py | 16 ----------------
nw/__init__.py | 4 ++--
2 files changed, 2 insertions(+), 18 deletions(-)
diff --git a/novelWriter.py b/novelWriter.py
index 3aa88038..1d4b711a 100755
--- a/novelWriter.py
+++ b/novelWriter.py
@@ -3,10 +3,6 @@
import sys
-if sys.hexversion < 0x030600F0:
- print("ERROR: At least Python 3.6 is required")
- sys.exit(1)
-
try:
import PyQt5.QtWidgets
import PyQt5.QtGui
@@ -15,18 +11,6 @@ except:
print("ERROR: Failed to load dependency python3-pyqt5")
sys.exit(1)
-try:
- import PyQt5.QtSvg
-except:
- print("ERROR: Failed to load dependency python3-pyqt5.qtsvg")
- sys.exit(1)
-
-try:
- import lxml
-except:
- print("ERROR: Failed to load dependency python3-lxml")
- sys.exit(1)
-
if __name__ == "__main__":
import nw
nw.main(sys.argv[1:])
diff --git a/nw/__init__.py b/nw/__init__.py
index 8010c267..83debe7d 100644
--- a/nw/__init__.py
+++ b/nw/__init__.py
@@ -67,7 +67,7 @@ __credits__ = [
# VERBOSE Use for outputting values and program flow details
#
-# Adding verbose logging levels
+# Add verbose logging level
VERBOSE = 5
logging.addLevelName(VERBOSE, "VERBOSE")
def logVerbose(self, message, *args, **kws):
@@ -254,8 +254,8 @@ def main(sysArgs=None):
errApp.exec_()
sys.exit(1)
+ # Finish initialising config, and launch GUI
CONFIG.initConfig(confPath, dataPath)
-
if testMode:
nwGUI = GuiMain()
return nwGUI
From 24596f28d623f58569a9ffebc1d21bab3bab9566 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 16 May 2020 19:04:52 +0200
Subject: [PATCH 3/9] Some more tuning of the documents margin function
---
nw/gui/elements/doceditor.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py
index 78f07c4c..a51f3212 100644
--- a/nw/gui/elements/doceditor.py
+++ b/nw/gui/elements/doceditor.py
@@ -257,7 +257,6 @@ class GuiDocEditor(QTextEdit):
self.setPlainText(theDoc)
afTime = time()
logger.debug("Document highlighted in %.3f milliseconds" % (1000*(afTime-bfTime)))
- self.updateDocMargins()
if tLine is None:
self.setCursorPosition(self.nwDocument.theItem.cursorPos)
@@ -275,6 +274,7 @@ class GuiDocEditor(QTextEdit):
self.theParent.noticeBar.showNote("This document is read only.")
self.docTitle.setTitleFromHandle(self.theHandle)
+ self.updateDocMargins()
self.hLight.spellCheck = spTemp
qApp.restoreOverrideCursor()
@@ -354,7 +354,7 @@ class GuiDocEditor(QTextEdit):
# The line below causes issues with large documents as it
# triggers an early repaint that seems to only render a part of
# the document. Leaving it here as a warning for now.
- # self.qDocument.contentsChange.emit(0,0,0)
+ # self.qDocument.contentsChange.emit(0, 0, 0)
return
From bb894926d0d72590a22d19d3466e5d7c15349b71 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 16 May 2020 20:18:39 +0200
Subject: [PATCH 4/9] With a few modifications, novelWriter now starts wuth Qt
5.2.1 and Python 3.4.3
---
nw/config.py | 8 ++++++--
nw/gui/dialogs/projecteditor.py | 2 +-
nw/gui/tools/dochighlight.py | 3 ++-
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/nw/config.py b/nw/config.py
index 7bc3bf77..e2a45e71 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -176,8 +176,12 @@ class Config:
self.osUnknown = True
# Other System Info
- self.hostName = QSysInfo.machineHostName()
- self.kernelVer = QSysInfo.kernelVersion()
+ if self.verQtValue >= 50600:
+ self.hostName = QSysInfo.machineHostName()
+ self.kernelVer = QSysInfo.kernelVersion()
+ else:
+ self.hostName = "Unknown"
+ self.kernelVer = "Unknown"
# Packages
self.hasEnchant = False
diff --git a/nw/gui/dialogs/projecteditor.py b/nw/gui/dialogs/projecteditor.py
index 6e8b63be..ff6171cd 100644
--- a/nw/gui/dialogs/projecteditor.py
+++ b/nw/gui/dialogs/projecteditor.py
@@ -296,7 +296,7 @@ class GuiProjectEditStatus(QWidget):
newItem.setIcon(QIcon(newIcon))
newItem.setData(Qt.UserRole, len(self.colData))
self.listBox.addItem(newItem)
- self.colData.append((iName,*iCol,oName))
+ self.colData.append((iName,iCol[0],iCol[1],iCol[2],oName))
self.colCounts.append(nUse)
return newItem
diff --git a/nw/gui/tools/dochighlight.py b/nw/gui/tools/dochighlight.py
index fbe3a02e..5ac14af5 100644
--- a/nw/gui/tools/dochighlight.py
+++ b/nw/gui/tools/dochighlight.py
@@ -91,7 +91,8 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.colTagErr = QColor(*self.theTheme.colTagErr)
self.colRepTag = QColor(*self.theTheme.colRepTag)
self.colMod = QColor(*self.theTheme.colMod)
- self.colTrail = QColor(*self.theTheme.colEmph,64)
+ self.colTrail = QColor(*self.theTheme.colEmph)
+ self.colTrail.setAlpha(64)
self.hStyles = {
"header1" : self._makeFormat(self.colHead, "bold",1.8),
From 92fc81d4ec6a9368ad9061b387b48837020dc409 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 16 May 2020 20:39:58 +0200
Subject: [PATCH 5/9] Reduced hard requirement of python version
---
README.md | 5 ++++-
nw/__init__.py | 4 ++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 12126c70..775babe0 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,10 @@ There are no launcher icons yet.
Consult your operating system documentation for how to make those.
These will be added at some point, and I would appreciate any assistance from people working on Windows and MacOS as I don't use either of those operating systems.
-## Dependencies
+## Package Dependencies
+
+It is recommended that novelWriter runs with Qt 5.9 or later, and Python 3.6 or later.
+Running with Qt as low as 5.2.1 and Python 3.4.3 has been tested, and worked in the past, but there are no guarantees that this will keep working as these are not a part of the test builds.
For the apt package manager on Debian systems, the following Python3 packages are needed:
diff --git a/nw/__init__.py b/nw/__init__.py
index 83debe7d..e09f686a 100644
--- a/nw/__init__.py
+++ b/nw/__init__.py
@@ -219,9 +219,9 @@ def main(sysArgs=None):
# Check Packages and Versions
errorData = []
- if sys.hexversion < 0x030600F0:
+ if sys.hexversion < 0x030403F0:
errorData.append(
- "At least Python 3.6 is required."
+ "At least Python 3.4.3 is required, but 3.6 is highly recommended."
)
if CONFIG.verQtValue < 50200:
errorData.append(
From 4dc768bdd244e34841c0a6679a2f6acf638fb3e9 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 16 May 2020 21:56:26 +0200
Subject: [PATCH 6/9] Dropped the progress bar for rebuild index, and used
statusbar instead
---
nw/core/document.py | 2 ++
nw/core/project.py | 1 -
nw/gui/elements/doceditor.py | 21 ++++++++++------
nw/gui/statusbar.py | 25 ++++++++++++++++---
nw/guimain.py | 48 ++++++++++++++++--------------------
5 files changed, 58 insertions(+), 39 deletions(-)
diff --git a/nw/core/document.py b/nw/core/document.py
index aaef4e9e..6bcba588 100644
--- a/nw/core/document.py
+++ b/nw/core/document.py
@@ -73,6 +73,8 @@ class NWDoc():
"""Open a document from handle, capturing potential file system
errors and parse meta data.
"""
+ # Always clear first, since the object will often be reused.
+ self.clearDocument()
self.docHandle = tHandle
if not isOrphan:
diff --git a/nw/core/project.py b/nw/core/project.py
index a7f2cd9b..84f89160 100644
--- a/nw/core/project.py
+++ b/nw/core/project.py
@@ -940,7 +940,6 @@ class NWProject():
oName = ""
if aDoc.openDocument(oHandle, showStatus=False, isOrphan=True):
oName, oPath = aDoc.getMeta()
- aDoc.clearDocument()
if oName == "":
nOrph += 1
diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py
index a51f3212..69d74b59 100644
--- a/nw/gui/elements/doceditor.py
+++ b/nw/gui/elements/doceditor.py
@@ -216,18 +216,23 @@ class GuiDocEditor(QTextEdit):
# font changed, otherwise we just clear the editor entirely,
# which makes it read only.
if self.theHandle is not None:
- # We must save the current handle as clearEditor() sets it
- # to None
- tHandle = self.theHandle
- self.clearEditor()
- self.loadText(tHandle)
- self.updateDocMargins()
+ self.reloadText()
else:
self.clearEditor()
return True
- def loadText(self, tHandle, tLine=None):
+ def reloadText(self):
+ """Reloads the document currently being edited.
+ """
+ if self.theHandle is not None:
+ tHandle = self.theHandle
+ self.clearEditor()
+ self.loadText(tHandle, showStatus=False)
+ self.updateDocMargins()
+ return
+
+ def loadText(self, tHandle, tLine=None, showStatus=True):
"""Load text from a document into the editor. If we have an io
error, we must handle this and clear the editor so that we don't
risk overwriting the file if it exists. This can for instance
@@ -237,7 +242,7 @@ class GuiDocEditor(QTextEdit):
the file.
"""
- theDoc = self.nwDocument.openDocument(tHandle)
+ theDoc = self.nwDocument.openDocument(tHandle, showStatus=showStatus)
if theDoc is None:
# There was an io error
self.clearEditor()
diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py
index 50f218f5..70aa0b90 100644
--- a/nw/gui/statusbar.py
+++ b/nw/gui/statusbar.py
@@ -32,7 +32,7 @@ from time import time
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QColor, QPixmap, QFont
-from PyQt5.QtWidgets import QStatusBar, QLabel
+from PyQt5.QtWidgets import qApp, QStatusBar, QLabel
from nw.core import NWSpellCheck
@@ -114,23 +114,32 @@ class GuiMainStatus(QStatusBar):
return
def clearStatus(self):
+ """Reset all widgets on the status bar to default values.
+ """
self.setRefTime(None)
- self.setStats(0,0)
- self.setCounts(0,0,0)
+ self.setStats(0, 0)
+ self.setCounts(0, 0, 0)
self.setProjectStatus(None)
self.setDocumentStatus(None)
self._updateTime()
return True
def setRefTime(self, theTime):
+ """Set the reference time for the status bar clock.
+ """
self.refTime = theTime
return
def setStatus(self, theMessage, timeOut=10.0):
+ """Set the status bar message to display for 'timeOut' seconds.
+ """
self.showMessage(theMessage, int(timeOut*1000))
+ qApp.processEvents()
return
def setLanguage(self, theLanguage):
+ """Set the language code for the spell checker.
+ """
if theLanguage is None:
self.langBox.setText("None")
else:
@@ -138,6 +147,8 @@ class GuiMainStatus(QStatusBar):
return
def setProjectStatus(self, isChanged):
+ """Set the project status colour icon.
+ """
if isChanged is None:
self.projChanged.setPixmap(self.iconGrey)
elif isChanged == True:
@@ -149,6 +160,8 @@ class GuiMainStatus(QStatusBar):
return
def setDocumentStatus(self, isChanged):
+ """Set the document status colour icon.
+ """
if isChanged is None:
self.docChanged.setPixmap(self.iconGrey)
elif isChanged == True:
@@ -160,10 +173,14 @@ class GuiMainStatus(QStatusBar):
return
def setStats(self, pWC, sWC):
+ """Set the current project statistics.
+ """
self.boxStats.setText("Project: {:d} : {:d}".format(pWC,sWC))
return
def setCounts(self, cC, wC, pC):
+ """Set the current document statistics.
+ """
self.boxCounts.setText("Document: {:d} : {:d} : {:d}".format(cC,wC,pC))
return
@@ -172,6 +189,8 @@ class GuiMainStatus(QStatusBar):
##
def _updateTime(self):
+ """Update the session clock.
+ """
if self.refTime is None:
theTime = "00:00:00"
else:
diff --git a/nw/guimain.py b/nw/guimain.py
index 00dc3f7d..782e8829 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -26,17 +26,17 @@
"""
import logging
-import time
import nw
from os import path
from datetime import datetime
+from time import time
from PyQt5.QtCore import Qt, QTimer
-from PyQt5.QtGui import QIcon, QPixmap, QColor, QKeySequence
+from PyQt5.QtGui import QIcon, QPixmap, QColor, QKeySequence, QCursor
from PyQt5.QtWidgets import (
qApp, QMainWindow, QVBoxLayout, QFrame, QSplitter, QFileDialog, QShortcut,
- QMessageBox, QProgressDialog, QDialog, QTabWidget
+ QMessageBox, QDialog, QTabWidget
)
from nw.gui import (
@@ -635,6 +635,8 @@ class GuiMain(QMainWindow):
return
def rebuildTree(self):
+ """Rebuild the project tree.
+ """
self._makeStatusIcons()
self._makeImportIcons()
self.treeView.clearTree()
@@ -642,37 +644,25 @@ class GuiMain(QMainWindow):
return
def rebuildIndex(self):
+ """Rebuild the entire index.
+ """
if not self.hasProject:
return False
- logger.debug("Rebuilding indices ...")
+ logger.debug("Rebuilding index ...")
+ qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
+ tStart = time()
self.treeView.saveTreeOrder()
self.theIndex.clearIndex()
nItems = len(self.theProject.projTree)
- dlgProg = QProgressDialog("Scanning files ...", "Cancel", 0, nItems, self)
- dlgProg.setWindowModality(Qt.WindowModal)
- dlgProg.setMinimumDuration(0)
- dlgProg.setFixedWidth(480)
- dlgProg.setLabelText("Starting file scan ...")
- dlgProg.setValue(0)
- dlgProg.show()
- time.sleep(0.5)
-
- nDone = 0
- for tItem in self.theProject.projTree:
-
- dlgProg.setValue(nDone)
-
+ theDoc = NWDoc(self.theProject, self)
+ for nDone, tItem in enumerate(self.theProject.projTree):
if tItem is not None and tItem.itemType == nwItemType.FILE:
-
- dlgProg.setLabelText("Scanning: %s" % tItem.itemName)
logger.verbose("Scanning: %s" % tItem.itemName)
-
- theDoc = NWDoc(self.theProject, self)
- theText = theDoc.openDocument(tItem.itemHandle, False)
+ theText = theDoc.openDocument(tItem.itemHandle, showStatus=False)
# Build tag index
self.theIndex.scanText(tItem.itemHandle, theText)
@@ -685,11 +675,15 @@ class GuiMain(QMainWindow):
self.treeView.propagateCount(tItem.itemHandle, wC)
self.treeView.projectWordCount()
- nDone += 1
- if dlgProg.wasCanceled():
- break
+ self.statusBar.setStatus("Building index: %.2f%%" % (100.0*(nDone + 1)/nItems))
- dlgProg.setValue(nItems)
+ self.docEditor.reloadText()
+ qApp.restoreOverrideCursor()
+ tEnd = time()
+
+ self.makeAlert(
+ "Project index rebuilt in %.3f seconds." % (tEnd - tStart), nwAlert.INFO
+ )
return True
From 3b231978bf691dd34652343dd27b02e304945674 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 16 May 2020 23:58:55 +0200
Subject: [PATCH 7/9] Several improvements to the status bar
---
.../icons/fallback/status_stats-dark.svg | 56 +++++
nw/assets/icons/fallback/status_stats.svg | 56 +++++
nw/gui/icons.py | 1 +
nw/gui/statusbar.py | 213 ++++++++++++------
4 files changed, 261 insertions(+), 65 deletions(-)
create mode 100644 nw/assets/icons/fallback/status_stats-dark.svg
create mode 100644 nw/assets/icons/fallback/status_stats.svg
diff --git a/nw/assets/icons/fallback/status_stats-dark.svg b/nw/assets/icons/fallback/status_stats-dark.svg
new file mode 100644
index 00000000..81fd5b96
--- /dev/null
+++ b/nw/assets/icons/fallback/status_stats-dark.svg
@@ -0,0 +1,56 @@
+
+
diff --git a/nw/assets/icons/fallback/status_stats.svg b/nw/assets/icons/fallback/status_stats.svg
new file mode 100644
index 00000000..a6727601
--- /dev/null
+++ b/nw/assets/icons/fallback/status_stats.svg
@@ -0,0 +1,56 @@
+
+
diff --git a/nw/gui/icons.py b/nw/gui/icons.py
index 35bc8122..c1a791d1 100644
--- a/nw/gui/icons.py
+++ b/nw/gui/icons.py
@@ -60,6 +60,7 @@ class GuiIcons:
"proj_folder" : (QStyle.SP_DirIcon, "folder"),
"status_lang" : (None, None),
"status_time" : (None, None),
+ "status_stats" : (None, None),
## Button Icons
"folder-open" : (QStyle.SP_DirOpenIcon, "folder-open"),
"delete" : (QStyle.SP_DialogDiscardButton, "edit-delete"),
diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py
index 70aa0b90..6d104357 100644
--- a/nw/gui/statusbar.py
+++ b/nw/gui/statusbar.py
@@ -31,10 +31,11 @@ import nw
from time import time
from PyQt5.QtCore import Qt, QTimer
-from PyQt5.QtGui import QColor, QPixmap, QFont
-from PyQt5.QtWidgets import qApp, QStatusBar, QLabel
+from PyQt5.QtGui import QColor, QPixmap, QFont, QPainter
+from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
from nw.core import NWSpellCheck
+from nw.common import formatInt
logger = logging.getLogger(__name__)
@@ -49,59 +50,71 @@ class GuiMainStatus(QStatusBar):
self.theParent = theParent
self.refTime = None
- self.iconGrey = QPixmap(16,16)
- self.iconYellow = QPixmap(16,16)
- self.iconGreen = QPixmap(16,16)
+ self.charCount = 0
+ self.wordCount = 0
+ self.paraCount = 0
+ self.projWords = 0
+ self.sessWords = 0
self.monoFont = QFont("Monospace",10)
- self.iconGrey.fill(QColor(*self.theParent.theTheme.statNone))
- self.iconYellow.fill(QColor(*self.theParent.theTheme.statUnsaved))
- self.iconGreen.fill(QColor(*self.theParent.theTheme.statSaved))
+ colNone = QColor(*self.theParent.theTheme.statNone)
+ colTrue = QColor(*self.theParent.theTheme.statUnsaved)
+ colFalse = QColor(*self.theParent.theTheme.statSaved)
- self.boxStats = QLabel()
- self.boxStats.setToolTip("Project Word Count | Session Word Count")
+ # Permanent Widgets
+ # =================
- self.timeBox = QLabel("")
- self.timeBox.setToolTip("Session Time")
- self.timeBox.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
- self.timeBox.setFont(self.monoFont)
-
- self.timeIcon = QLabel()
- self.timeIcon.setPixmap(self.theParent.theTheme.getPixmap("status_time",(14,14)))
-
- self.boxCounts = QLabel()
- self.boxCounts.setToolTip("Document Character | Word | Paragraph Count")
-
- self.projChanged = QLabel("")
- self.projChanged.setFixedHeight(14)
- self.projChanged.setFixedWidth(14)
- self.projChanged.setToolTip("Project Changes Saved")
-
- self.docChanged = QLabel("")
- self.docChanged.setFixedHeight(14)
- self.docChanged.setFixedWidth(14)
- self.docChanged.setToolTip("Document Changes Saved")
-
- self.langBox = QLabel("None")
+ ## The Spell Checker Language
self.langIcon = QLabel("")
+ self.langText = QLabel("None")
self.langIcon.setPixmap(self.theParent.theTheme.getPixmap("status_lang",(14,14)))
-
- # Add Them
+ self.langIcon.setContentsMargins(0, 0, 0, 0)
+ self.langText.setContentsMargins(0, 0, 8, 0)
self.addPermanentWidget(self.langIcon)
- self.addPermanentWidget(self.langBox)
- self.addPermanentWidget(QLabel(" "))
- self.addPermanentWidget(self.docChanged)
- self.addPermanentWidget(self.boxCounts)
- self.addPermanentWidget(QLabel(" "))
- self.addPermanentWidget(self.projChanged)
- self.addPermanentWidget(self.boxStats)
- self.addPermanentWidget(QLabel(" "))
- self.addPermanentWidget(self.timeIcon)
- self.addPermanentWidget(self.timeBox)
+ self.addPermanentWidget(self.langText)
+ ## The Editor Status
+ self.docIcon = StatusLED(colNone, colTrue, colFalse, 14, 14, self)
+ self.docText = QLabel("Editor")
+ self.docIcon.setContentsMargins(0, 0, 0, 0)
+ self.docText.setContentsMargins(0, 0, 8, 0)
+ self.addPermanentWidget(self.docIcon)
+ self.addPermanentWidget(self.docText)
+
+ ## The Project Status
+ self.projIcon = StatusLED(colNone, colTrue, colFalse, 14, 14, self)
+ self.projText = QLabel("Project")
+ self.projIcon.setContentsMargins(0, 0, 0, 0)
+ self.projText.setContentsMargins(0, 0, 8, 0)
+ self.addPermanentWidget(self.projIcon)
+ self.addPermanentWidget(self.projText)
+
+ ## The Project and Session Stats
+ self.statsIcon = QLabel()
+ self.statsText = QLabel("")
+ self.statsIcon.setPixmap(self.theParent.theTheme.getPixmap("status_stats",(14,14)))
+ self.statsIcon.setContentsMargins(0, 0, 0, 0)
+ self.statsText.setContentsMargins(0, 0, 8, 0)
+ self.addPermanentWidget(self.statsIcon)
+ self.addPermanentWidget(self.statsText)
+
+ ## The Session Clock
+ self.timeIcon = QLabel()
+ self.timeText = QLabel("")
+ self.timeIcon.setPixmap(self.theParent.theTheme.getPixmap("status_time",(14,14)))
+ self.timeText.setToolTip("Session Time")
+ self.timeText.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
+ self.timeText.setFont(self.monoFont)
+ self.timeIcon.setContentsMargins(0, 0, 0, 0)
+ self.timeText.setContentsMargins(0, 0, 0, 0)
+ self.addPermanentWidget(self.timeIcon)
+ self.addPermanentWidget(self.timeText)
+
+ # Other Settings
self.setSizeGripEnabled(True)
+ # Start the Clock
self.sessionTimer = QTimer()
self.sessionTimer.setInterval(1000)
self.sessionTimer.timeout.connect(self._updateTime)
@@ -141,53 +154,72 @@ class GuiMainStatus(QStatusBar):
"""Set the language code for the spell checker.
"""
if theLanguage is None:
- self.langBox.setText("None")
+ self.langText.setText("None")
else:
- self.langBox.setText(NWSpellCheck.expandLanguage(theLanguage))
+ self.langText.setText(NWSpellCheck.expandLanguage(theLanguage))
return
def setProjectStatus(self, isChanged):
"""Set the project status colour icon.
"""
- if isChanged is None:
- self.projChanged.setPixmap(self.iconGrey)
- elif isChanged == True:
- self.projChanged.setPixmap(self.iconYellow)
- elif isChanged == False:
- self.projChanged.setPixmap(self.iconGreen)
- else:
- self.projChanged.setPixmap(self.iconGrey)
+ self.projIcon.setState(isChanged)
return
def setDocumentStatus(self, isChanged):
"""Set the document status colour icon.
"""
- if isChanged is None:
- self.docChanged.setPixmap(self.iconGrey)
- elif isChanged == True:
- self.docChanged.setPixmap(self.iconYellow)
- elif isChanged == False:
- self.docChanged.setPixmap(self.iconGreen)
- else:
- self.docChanged.setPixmap(self.iconGrey)
+ self.docIcon.setState(isChanged)
return
def setStats(self, pWC, sWC):
"""Set the current project statistics.
"""
- self.boxStats.setText("Project: {:d} : {:d}".format(pWC,sWC))
+ self.projWords = pWC
+ self.sessWords = sWC
+ self._updateStats()
return
def setCounts(self, cC, wC, pC):
"""Set the current document statistics.
"""
- self.boxCounts.setText("Document: {:d} : {:d} : {:d}".format(cC,wC,pC))
+ self.charCount = cC
+ self.wordCount = wC
+ self.paraCount = pC
+ self._updateStats()
return
##
# Internal Functions
##
+ def _updateStats(self):
+ """Update statistics.
+ """
+ self.statsText.setToolTip((
+ "Document Stats
"
+ "Characters: {cC:n}
"
+ "Words: {wC:n}
"
+ "Paragraphs: {pC:n}
"
+ "
"
+ "Project Stats
"
+ "Words Total: {pWC:n}
"
+ "This Session: {sWC:n}"
+ ).format(
+ cC = self.charCount,
+ wC = self.wordCount,
+ pC = self.paraCount,
+ pWC = self.projWords,
+ sWC = self.sessWords,
+ ))
+ self.statsText.setText((
+ "D:{wC:n} P:{pWC:n} S:{sWC:n}"
+ ).format(
+ wC = self.wordCount,
+ pWC = self.projWords,
+ sWC = self.sessWords,
+ ))
+ return
+
def _updateTime(self):
"""Update the session clock.
"""
@@ -201,7 +233,58 @@ class GuiMainStatus(QStatusBar):
tM = tM - tH*60
tS = tS - tM*60 - tH*3600
theTime = "%02d:%02d:%02d" % (tH,tM,tS)
- self.timeBox.setText(theTime)
+ self.timeText.setText(theTime)
return
# END Class GuiMainStatus
+
+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.setFixedWidth(sW)
+ self.setFixedHeight(sH)
+
+ return
+
+ ##
+ # Getters and Setters
+ ##
+
+ def setState(self, theState):
+ """Set the colour state.
+ """
+ if theState is None:
+ self._theCol = self.colNone
+ elif theState == True:
+ self._theCol = self.colTrue
+ elif theState == False:
+ self._theCol = self.colFalse
+ else:
+ self._theCol = self.colNone
+ self.update()
+ return
+
+ ##
+ # Events
+ ##
+
+ def paintEvent(self, event):
+ """Drawing the LED.
+ """
+ qPalette = self.palette()
+ qPaint = QPainter(self)
+ qPaint.setRenderHint(QPainter.Antialiasing, True)
+ qPaint.setPen(qPalette.dark().color())
+ qPaint.setBrush(self._theCol)
+ qPaint.setOpacity(1.0)
+ qPaint.drawEllipse(1, 1, self.width()-2, self.height()-2)
+ return
+
+# END Class StatusLED
From c1b508aae85c8f2f77d76d9d9cc03c725021495c Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sun, 17 May 2020 00:09:49 +0200
Subject: [PATCH 8/9] Fix the dependency checks
---
nw/__init__.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/nw/__init__.py b/nw/__init__.py
index e09f686a..9d27b993 100644
--- a/nw/__init__.py
+++ b/nw/__init__.py
@@ -34,7 +34,6 @@ from os import path, remove, rename
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QErrorMessage
-from nw.guimain import GuiMain
from nw.config import Config
__package__ = "novelWriter"
@@ -254,8 +253,11 @@ def main(sysArgs=None):
errApp.exec_()
sys.exit(1)
- # Finish initialising config, and launch GUI
+ # Finish initialising config
CONFIG.initConfig(confPath, dataPath)
+
+ # Import GUI (after dependency checks), and launch
+ from nw.guimain import GuiMain
if testMode:
nwGUI = GuiMain()
return nwGUI
From e70a05718818fe1e140b98cefb842d4b4e497d66 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sun, 17 May 2020 00:16:25 +0200
Subject: [PATCH 9/9] Index rebuild dialog box was blocking test.
---
nw/guimain.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/nw/guimain.py b/nw/guimain.py
index 782e8829..6278f47f 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -681,9 +681,10 @@ class GuiMain(QMainWindow):
qApp.restoreOverrideCursor()
tEnd = time()
- self.makeAlert(
- "Project index rebuilt in %.3f seconds." % (tEnd - tStart), nwAlert.INFO
- )
+ if self.mainConf.showGUI:
+ self.makeAlert(
+ "Project index rebuilt in %.3f seconds." % (tEnd - tStart), nwAlert.INFO
+ )
return True