+9
-3
@@ -35,6 +35,8 @@ from nw.constants import nwConst
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def checkString(checkValue, defaultValue, allowNone=False):
|
def checkString(checkValue, defaultValue, allowNone=False):
|
||||||
|
"""Check if a variable is a string or a none.
|
||||||
|
"""
|
||||||
if allowNone:
|
if allowNone:
|
||||||
if checkValue == None:
|
if checkValue == None:
|
||||||
return None
|
return None
|
||||||
@@ -45,6 +47,8 @@ def checkString(checkValue, defaultValue, allowNone=False):
|
|||||||
return defaultValue
|
return defaultValue
|
||||||
|
|
||||||
def checkInt(checkValue, defaultValue, allowNone=False):
|
def checkInt(checkValue, defaultValue, allowNone=False):
|
||||||
|
"""Check if a variable is an integer or a none.
|
||||||
|
"""
|
||||||
if allowNone:
|
if allowNone:
|
||||||
if checkValue == None:
|
if checkValue == None:
|
||||||
return None
|
return None
|
||||||
@@ -56,6 +60,8 @@ def checkInt(checkValue, defaultValue, allowNone=False):
|
|||||||
return defaultValue
|
return defaultValue
|
||||||
|
|
||||||
def checkBool(checkValue, defaultValue, allowNone=False):
|
def checkBool(checkValue, defaultValue, allowNone=False):
|
||||||
|
"""Check if a variable is a boolean or a none.
|
||||||
|
"""
|
||||||
if allowNone:
|
if allowNone:
|
||||||
if checkValue == None:
|
if checkValue == None:
|
||||||
return None
|
return None
|
||||||
@@ -92,7 +98,8 @@ def isHandle(theString):
|
|||||||
return not invalidChar
|
return not invalidChar
|
||||||
|
|
||||||
def colRange(rgbStart, rgbEnd, nStep):
|
def colRange(rgbStart, rgbEnd, nStep):
|
||||||
|
"""Generate a range of colours from one RGB value to another.
|
||||||
|
"""
|
||||||
if len(rgbStart) != 3 and len(rgbEnd) != 3 and nStep < 1:
|
if len(rgbStart) != 3 and len(rgbEnd) != 3 and nStep < 1:
|
||||||
logger.error("Cannot create colour range from given parameters")
|
logger.error("Cannot create colour range from given parameters")
|
||||||
return None
|
return None
|
||||||
@@ -124,7 +131,7 @@ def colRange(rgbStart, rgbEnd, nStep):
|
|||||||
def formatInt(theInt):
|
def formatInt(theInt):
|
||||||
"""Formats an integer with k, M, G etc.
|
"""Formats an integer with k, M, G etc.
|
||||||
"""
|
"""
|
||||||
postFix = ["k","M","G","T","P","E"]
|
postFix = ["k", "M", "G", "T", "P", "E"]
|
||||||
theVal = float(theInt)
|
theVal = float(theInt)
|
||||||
|
|
||||||
if theVal > 1000.0:
|
if theVal > 1000.0:
|
||||||
@@ -153,7 +160,6 @@ def splitVersionNumber(vString):
|
|||||||
""" Splits a version string on the form aa.bb.cc into major, minor
|
""" Splits a version string on the form aa.bb.cc into major, minor
|
||||||
and patch, and computes an integer value aabbcc.
|
and patch, and computes an integer value aabbcc.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
vMajor = 0
|
vMajor = 0
|
||||||
vMinor = 0
|
vMinor = 0
|
||||||
vPatch = 0
|
vPatch = 0
|
||||||
|
|||||||
+11
-3
@@ -88,7 +88,7 @@ class Config:
|
|||||||
self.guiSyntax = "default_light"
|
self.guiSyntax = "default_light"
|
||||||
self.guiIcons = "typicons_colour_light"
|
self.guiIcons = "typicons_colour_light"
|
||||||
self.guiDark = False
|
self.guiDark = False
|
||||||
self.guiLang = "en" # Hardcoded for now
|
self.guiLang = "en" # Hardcoded for now since the GUI is only in English
|
||||||
self.guiFont = ""
|
self.guiFont = ""
|
||||||
self.guiFontSize = 11
|
self.guiFontSize = 11
|
||||||
self.guiScale = 1.0 # Set automatically by Theme class
|
self.guiScale = 1.0 # Set automatically by Theme class
|
||||||
@@ -286,7 +286,7 @@ class Config:
|
|||||||
|
|
||||||
# Check if config file exists
|
# Check if config file exists
|
||||||
if self.confPath is not None:
|
if self.confPath is not None:
|
||||||
if path.isfile(path.join(self.confPath,self.confFile)):
|
if path.isfile(path.join(self.confPath, self.confFile)):
|
||||||
# If it exists, load it
|
# If it exists, load it
|
||||||
self.loadConfig()
|
self.loadConfig()
|
||||||
else:
|
else:
|
||||||
@@ -855,7 +855,9 @@ class Config:
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _unpackList(self, inStr, listLen, listDefault, castTo=int):
|
def _unpackList(self, inStr, listLen, listDefault, castTo=int):
|
||||||
inData = inStr.split(",")
|
"""Unpack a comma separated string of items into a list.
|
||||||
|
"""
|
||||||
|
inData = inStr.split(",")
|
||||||
outData = []
|
outData = []
|
||||||
for i in range(listLen):
|
for i in range(listLen):
|
||||||
try:
|
try:
|
||||||
@@ -865,9 +867,13 @@ class Config:
|
|||||||
return outData
|
return outData
|
||||||
|
|
||||||
def _packList(self, inData):
|
def _packList(self, inData):
|
||||||
|
"""Pack a list of items into a comma separated string.
|
||||||
|
"""
|
||||||
return ", ".join(str(inVal) for inVal in inData)
|
return ", ".join(str(inVal) for inVal in inData)
|
||||||
|
|
||||||
def _parseLine(self, cnfParse, cnfSec, cnfName, cnfType, cnfDefault):
|
def _parseLine(self, cnfParse, cnfSec, cnfName, cnfType, cnfDefault):
|
||||||
|
"""Parse a line and return the correct datatype.
|
||||||
|
"""
|
||||||
if cnfParse.has_section(cnfSec):
|
if cnfParse.has_section(cnfSec):
|
||||||
if cnfParse.has_option(cnfSec, cnfName):
|
if cnfParse.has_option(cnfSec, cnfName):
|
||||||
if cnfType == self.CNF_STR:
|
if cnfType == self.CNF_STR:
|
||||||
@@ -883,6 +889,8 @@ class Config:
|
|||||||
return cnfDefault
|
return cnfDefault
|
||||||
|
|
||||||
def _checkNone(self, checkVal):
|
def _checkNone(self, checkVal):
|
||||||
|
"""Convert a string to a none type.
|
||||||
|
"""
|
||||||
if checkVal is None:
|
if checkVal is None:
|
||||||
return None
|
return None
|
||||||
if isinstance(checkVal, str):
|
if isinstance(checkVal, str):
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from nw.constants.enum import nwItemClass, nwItemLayout, nwOutline, nwDocInsert
|
from nw.constants.enum import nwItemClass, nwItemLayout, nwOutline
|
||||||
|
|
||||||
class nwConst():
|
class nwConst():
|
||||||
|
|
||||||
|
|||||||
+6
-5
@@ -28,7 +28,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path, mkdir, rename, unlink
|
from os import path, rename, unlink
|
||||||
|
|
||||||
from nw.core.item import NWItem
|
from nw.core.item import NWItem
|
||||||
from nw.constants import nwAlert
|
from nw.constants import nwAlert
|
||||||
@@ -44,10 +44,11 @@ class NWDoc():
|
|||||||
self.mainConf = nw.CONFIG
|
self.mainConf = nw.CONFIG
|
||||||
self.theProject = theProject
|
self.theProject = theProject
|
||||||
self.theParent = theParent
|
self.theParent = theParent
|
||||||
self.theItem = None
|
|
||||||
self.docHandle = None
|
self.theItem = None
|
||||||
self.fileLoc = None
|
self.docHandle = None
|
||||||
self.docMeta = ""
|
self.fileLoc = None
|
||||||
|
self.docMeta = ""
|
||||||
|
|
||||||
# Internal Mapping
|
# Internal Mapping
|
||||||
self.makeAlert = self.theParent.makeAlert
|
self.makeAlert = self.theParent.makeAlert
|
||||||
|
|||||||
@@ -195,7 +195,6 @@ class NWSpellEnchant(NWSpellCheck):
|
|||||||
class NWSpellEnchantDummy:
|
class NWSpellEnchantDummy:
|
||||||
"""Fallback for when Enchant is selected, but not installed.
|
"""Fallback for when Enchant is selected, but not installed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -227,7 +227,6 @@ class Tokenizer():
|
|||||||
"""Set the text for the tokenizer from a handle. If theText is
|
"""Set the text for the tokenizer from a handle. If theText is
|
||||||
not set, load it from the file.
|
not set, load it from the file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.theHandle = theHandle
|
self.theHandle = theHandle
|
||||||
self.theItem = self.theProject.projTree[theHandle]
|
self.theItem = self.theProject.projTree[theHandle]
|
||||||
if self.theItem is None:
|
if self.theItem is None:
|
||||||
@@ -308,7 +307,6 @@ class Tokenizer():
|
|||||||
4: The internal formatting map of the text, self.FMT_*
|
4: The internal formatting map of the text, self.FMT_*
|
||||||
5: The style of the block, self.A_*
|
5: The style of the block, self.A_*
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# RegExes for adding formatting tags within text lines
|
# RegExes for adding formatting tags within text lines
|
||||||
rxFormats = [
|
rxFormats = [
|
||||||
(QRegularExpression(nwRegEx.FMT_I), [None, self.FMT_I_B, None, self.FMT_I_E]),
|
(QRegularExpression(nwRegEx.FMT_I), [None, self.FMT_I_B, None, self.FMT_I_E]),
|
||||||
@@ -457,7 +455,6 @@ class Tokenizer():
|
|||||||
"""Apply formatting to the text headers according to document
|
"""Apply formatting to the text headers according to document
|
||||||
layout and user settings.
|
layout and user settings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# No special header formatting for notes and no-layout files
|
# No special header formatting for notes and no-layout files
|
||||||
if self.isNone or self.isNote:
|
if self.isNone or self.isNote:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -30,8 +30,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path, unlink, rmdir
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|||||||
+3
-3
@@ -46,7 +46,7 @@ def formatHtmlErrMsg(exType, exValue, exTrace):
|
|||||||
"<p>Please report this error by submitting an issue report on "
|
"<p>Please report this error by submitting an issue report on "
|
||||||
"GitHub, providing a description and this error message. "
|
"GitHub, providing a description and this error message. "
|
||||||
"URL: <{issueUrl}>.</p>"
|
"URL: <{issueUrl}>.</p>"
|
||||||
"<p><b>Environment</b><br>Version: {nwVersion}, OS: {osType} ({osKernel}),"
|
"<p><b>Environment</b><br>Version: {nwVersion}, OS: {osType} ({osKernel}), "
|
||||||
"Python: {pyVersion} ({pyHexVer:#x}), Qt: {qtVers}, PyQt: {pyqtVers}</p>"
|
"Python: {pyVersion} ({pyHexVer:#x}), Qt: {qtVers}, PyQt: {pyqtVers}</p>"
|
||||||
"<p><b>Error Type</b><br>{exType}: {exMessage}</p>"
|
"<p><b>Error Type</b><br>{exType}: {exMessage}</p>"
|
||||||
"<p><b>Traceback</b><br>{exTrace}</p>"
|
"<p><b>Traceback</b><br>{exTrace}</p>"
|
||||||
@@ -76,9 +76,9 @@ def exceptionHandler(exType, exValue, exTrace):
|
|||||||
"""Function to catch unhandled global exceptions.
|
"""Function to catch unhandled global exceptions.
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from traceback import print_tb, format_tb
|
from traceback import print_tb
|
||||||
from nw import CONFIG
|
from nw import CONFIG
|
||||||
from PyQt5.QtWidgets import qApp, QApplication, QErrorMessage, QMessageBox
|
from PyQt5.QtWidgets import qApp, QErrorMessage
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logger.error("%s: %s" % (exType.__name__, str(exValue)))
|
logger.error("%s: %s" % (exType.__name__, str(exValue)))
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ from PyQt5.QtCore import (
|
|||||||
Qt, QSize, QThread, QTimer, pyqtSlot, QRegExp, QRegularExpression
|
Qt, QSize, QThread, QTimer, pyqtSlot, QRegExp, QRegularExpression
|
||||||
)
|
)
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette, QIcon,
|
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette,
|
||||||
QTextDocument, QCursor, QPixmap
|
QTextDocument, QCursor, QPixmap
|
||||||
)
|
)
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ class GuiDocMerge(QDialog):
|
|||||||
create a new file in the same parent folder. The old files are
|
create a new file in the same parent folder. The old files are
|
||||||
not removed in the merge process, and must be deleted manually.
|
not removed in the merge process, and must be deleted manually.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.verbose("GuiDocMerge merge button clicked")
|
logger.verbose("GuiDocMerge merge button clicked")
|
||||||
|
|
||||||
finalOrder = []
|
finalOrder = []
|
||||||
@@ -142,7 +141,6 @@ class GuiDocMerge(QDialog):
|
|||||||
are then added to the list view in order. The list itself can be
|
are then added to the list view in order. The list itself can be
|
||||||
reordered by the user.
|
reordered by the user.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tHandle = self.theParent.treeView.getSelectedHandle()
|
tHandle = self.theParent.treeView.getSelectedHandle()
|
||||||
self.sourceItem = tHandle
|
self.sourceItem = tHandle
|
||||||
if tHandle is None:
|
if tHandle is None:
|
||||||
|
|||||||
+2
-3
@@ -33,6 +33,7 @@ from PyQt5.QtWidgets import (
|
|||||||
QDialog, QVBoxLayout, QComboBox, QListWidget, QAbstractItemView,
|
QDialog, QVBoxLayout, QComboBox, QListWidget, QAbstractItemView,
|
||||||
QListWidgetItem, QDialogButtonBox, QLabel
|
QListWidgetItem, QDialogButtonBox, QLabel
|
||||||
)
|
)
|
||||||
|
|
||||||
from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout
|
from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout
|
||||||
from nw.gui.custom import QHelpLabel
|
from nw.gui.custom import QHelpLabel
|
||||||
from nw.core import NWDoc
|
from nw.core import NWDoc
|
||||||
@@ -109,7 +110,6 @@ class GuiDocSplit(QDialog):
|
|||||||
settings. The old file is not removed in the merge process, and
|
settings. The old file is not removed in the merge process, and
|
||||||
must be deleted manually.
|
must be deleted manually.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.verbose("GuiDocSplit split button clicked")
|
logger.verbose("GuiDocSplit split button clicked")
|
||||||
|
|
||||||
if self.sourceItem is None:
|
if self.sourceItem is None:
|
||||||
@@ -131,7 +131,7 @@ class GuiDocSplit(QDialog):
|
|||||||
nLines = len(theLines)
|
nLines = len(theLines)
|
||||||
theLines.insert(0, "%Split Doc")
|
theLines.insert(0, "%Split Doc")
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Splitting document %s with %d lines" % (self.sourceItem,nLines)
|
"Splitting document %s with %d lines" % (self.sourceItem, nLines)
|
||||||
)
|
)
|
||||||
|
|
||||||
finalOrder = []
|
finalOrder = []
|
||||||
@@ -209,7 +209,6 @@ class GuiDocSplit(QDialog):
|
|||||||
are then added to the list view in order. The list itself can be
|
are then added to the list view in order. The list itself can be
|
||||||
reordered by the user.
|
reordered by the user.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.sourceItem is None:
|
if self.sourceItem is None:
|
||||||
self.sourceItem = self.theParent.treeView.getSelectedHandle()
|
self.sourceItem = self.theParent.treeView.getSelectedHandle()
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ import logging
|
|||||||
import nw
|
import nw
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import QFont, QIcon, QPixmap
|
from PyQt5.QtGui import QFont, QPixmap
|
||||||
from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel
|
from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel
|
||||||
|
|
||||||
from nw.constants import (
|
from nw.constants import (
|
||||||
nwLabels, nwItemClass, nwItemType, nwItemLayout, nwUnicode
|
nwLabels, nwItemClass, nwItemType, nwItemLayout
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialog, QVBoxLayout, QGridLayout, QLineEdit, QComboBox, QLabel,
|
QDialog, QVBoxLayout, QGridLayout, QLineEdit, QComboBox, QLabel,
|
||||||
QDialogButtonBox
|
QDialogButtonBox
|
||||||
@@ -151,7 +150,6 @@ class GuiItemEditor(QDialog):
|
|||||||
def _doSave(self):
|
def _doSave(self):
|
||||||
"""Save the setting to the item.
|
"""Save the setting to the item.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.verbose("ItemEditor save button clicked")
|
logger.verbose("ItemEditor save button clicked")
|
||||||
|
|
||||||
itemName = self.editName.text()
|
itemName = self.editName.text()
|
||||||
@@ -172,6 +170,8 @@ class GuiItemEditor(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _doClose(self):
|
def _doClose(self):
|
||||||
|
"""Close the dialog without saving the settings.
|
||||||
|
"""
|
||||||
logger.verbose("ItemEditor close button clicked")
|
logger.verbose("ItemEditor close button clicked")
|
||||||
self.close()
|
self.close()
|
||||||
return
|
return
|
||||||
|
|||||||
+18
-9
@@ -192,7 +192,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _buildProjectMenu(self):
|
def _buildProjectMenu(self):
|
||||||
|
"""Assemble the Project menu.
|
||||||
|
"""
|
||||||
# Project
|
# Project
|
||||||
self.projMenu = self.addMenu("&Project")
|
self.projMenu = self.addMenu("&Project")
|
||||||
|
|
||||||
@@ -295,7 +296,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildDocumentMenu(self):
|
def _buildDocumentMenu(self):
|
||||||
|
"""Assemble the Document menu.
|
||||||
|
"""
|
||||||
# Document
|
# Document
|
||||||
self.docuMenu = self.addMenu("&Document")
|
self.docuMenu = self.addMenu("&Document")
|
||||||
|
|
||||||
@@ -377,7 +379,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildEditMenu(self):
|
def _buildEditMenu(self):
|
||||||
|
"""Assemble the Edit menu.
|
||||||
|
"""
|
||||||
# Edit
|
# Edit
|
||||||
self.editMenu = self.addMenu("&Edit")
|
self.editMenu = self.addMenu("&Edit")
|
||||||
|
|
||||||
@@ -439,7 +442,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildViewMenu(self):
|
def _buildViewMenu(self):
|
||||||
|
"""Assemble the View menu.
|
||||||
|
"""
|
||||||
# View
|
# View
|
||||||
self.viewMenu = self.addMenu("&View")
|
self.viewMenu = self.addMenu("&View")
|
||||||
|
|
||||||
@@ -486,7 +490,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildInsertMenu(self):
|
def _buildInsertMenu(self):
|
||||||
|
"""Assemble the Insert menu.
|
||||||
|
"""
|
||||||
# Insert
|
# Insert
|
||||||
self.insertMenu = self.addMenu("&Insert")
|
self.insertMenu = self.addMenu("&Insert")
|
||||||
|
|
||||||
@@ -576,7 +581,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildSearchMenu(self):
|
def _buildSearchMenu(self):
|
||||||
|
"""Assemble the Search menu.
|
||||||
|
"""
|
||||||
# Search
|
# Search
|
||||||
self.srcMenu = self.addMenu("&Search")
|
self.srcMenu = self.addMenu("&Search")
|
||||||
|
|
||||||
@@ -627,7 +633,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildFormatMenu(self):
|
def _buildFormatMenu(self):
|
||||||
|
"""Assemble the Format menu.
|
||||||
|
"""
|
||||||
# Format
|
# Format
|
||||||
self.fmtMenu = self.addMenu("&Format")
|
self.fmtMenu = self.addMenu("&Format")
|
||||||
|
|
||||||
@@ -732,7 +739,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildToolsMenu(self):
|
def _buildToolsMenu(self):
|
||||||
|
"""Assemble the Tools menu.
|
||||||
|
"""
|
||||||
# Tools
|
# Tools
|
||||||
self.toolsMenu = self.addMenu("&Tools")
|
self.toolsMenu = self.addMenu("&Tools")
|
||||||
|
|
||||||
@@ -828,7 +836,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _buildHelpMenu(self):
|
def _buildHelpMenu(self):
|
||||||
|
"""Assemble the Help menu.
|
||||||
|
"""
|
||||||
# Help
|
# Help
|
||||||
self.helpMenu = self.addMenu("&Help")
|
self.helpMenu = self.addMenu("&Help")
|
||||||
|
|
||||||
|
|||||||
@@ -195,8 +195,10 @@ class GuiOutline(QTreeWidget):
|
|||||||
tLine = int(tItem.text(self.colIndex[nwOutline.LINE]))
|
tLine = int(tItem.text(self.colIndex[nwOutline.LINE]))
|
||||||
except:
|
except:
|
||||||
tLine = 1
|
tLine = 1
|
||||||
|
|
||||||
logger.verbose("User selected entry with handle %s on line %s" % (tHandle, tLine))
|
logger.verbose("User selected entry with handle %s on line %s" % (tHandle, tLine))
|
||||||
self.theParent.openDocument(tHandle, tLine=tLine-1, doScroll=True)
|
self.theParent.openDocument(tHandle, tLine=tLine-1, doScroll=True)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _itemSelected(self):
|
def _itemSelected(self):
|
||||||
@@ -208,6 +210,7 @@ class GuiOutline(QTreeWidget):
|
|||||||
tHandle = selItems[0].data(self.colIndex[nwOutline.TITLE], Qt.UserRole)
|
tHandle = selItems[0].data(self.colIndex[nwOutline.TITLE], Qt.UserRole)
|
||||||
sTitle = selItems[0].data(self.colIndex[nwOutline.LINE], Qt.UserRole)
|
sTitle = selItems[0].data(self.colIndex[nwOutline.LINE], Qt.UserRole)
|
||||||
self.theParent.projMeta.showItem(tHandle, sTitle)
|
self.theParent.projMeta.showItem(tHandle, sTitle)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _headerRightClick(self, clickPos):
|
def _headerRightClick(self, clickPos):
|
||||||
@@ -232,6 +235,7 @@ class GuiOutline(QTreeWidget):
|
|||||||
if theItem in self.colIndex:
|
if theItem in self.colIndex:
|
||||||
self.setColumnHidden(self.colIndex[theItem], not isChecked)
|
self.setColumnHidden(self.colIndex[theItem], not isChecked)
|
||||||
self._saveHeaderState()
|
self._saveHeaderState()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ import nw
|
|||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QScrollArea, QWidget, QGridLayout, QHBoxLayout, QGroupBox, QLabel, QSizePolicy
|
QScrollArea, QWidget, QGridLayout, QHBoxLayout, QGroupBox, QLabel,
|
||||||
|
QSizePolicy
|
||||||
)
|
)
|
||||||
|
|
||||||
from nw.constants import nwLabels, nwKeyWords
|
from nw.constants import nwLabels, nwKeyWords
|
||||||
|
|||||||
+17
-6
@@ -80,7 +80,9 @@ class GuiPreferences(PagedDialog):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _doSave(self):
|
def _doSave(self):
|
||||||
|
"""Trigger all the save functions in the tabs, and collect the
|
||||||
|
status of the saves.
|
||||||
|
"""
|
||||||
logger.verbose("ConfigEditor save button clicked")
|
logger.verbose("ConfigEditor save button clicked")
|
||||||
|
|
||||||
validEntries = True
|
validEntries = True
|
||||||
@@ -115,6 +117,8 @@ class GuiPreferences(PagedDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _doClose(self):
|
def _doClose(self):
|
||||||
|
"""Close the preferences without saving the changes.
|
||||||
|
"""
|
||||||
logger.verbose("ConfigEditor close button clicked")
|
logger.verbose("ConfigEditor close button clicked")
|
||||||
self.close()
|
self.close()
|
||||||
return
|
return
|
||||||
@@ -284,7 +288,8 @@ class GuiConfigEditGeneralTab(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def saveValues(self):
|
def saveValues(self):
|
||||||
|
"""Save the values set for this tab.
|
||||||
|
"""
|
||||||
validEntries = True
|
validEntries = True
|
||||||
needsRestart = False
|
needsRestart = False
|
||||||
|
|
||||||
@@ -329,7 +334,6 @@ class GuiConfigEditGeneralTab(QWidget):
|
|||||||
def _backupFolder(self):
|
def _backupFolder(self):
|
||||||
"""Open a dialog to select the backup folder.
|
"""Open a dialog to select the backup folder.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
currDir = self.backupPath
|
currDir = self.backupPath
|
||||||
if not path.isdir(currDir):
|
if not path.isdir(currDir):
|
||||||
currDir = ""
|
currDir = ""
|
||||||
@@ -515,7 +519,8 @@ class GuiConfigEditLayoutTab(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def saveValues(self):
|
def saveValues(self):
|
||||||
|
"""Save the values set for this tab.
|
||||||
|
"""
|
||||||
validEntries = True
|
validEntries = True
|
||||||
needsRestart = False
|
needsRestart = False
|
||||||
|
|
||||||
@@ -681,7 +686,8 @@ class GuiConfigEditEditingTab(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def saveValues(self):
|
def saveValues(self):
|
||||||
|
"""Save the values set for this tab.
|
||||||
|
"""
|
||||||
validEntries = True
|
validEntries = True
|
||||||
needsRestart = False
|
needsRestart = False
|
||||||
|
|
||||||
@@ -712,6 +718,8 @@ class GuiConfigEditEditingTab(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _disableComboItem(self, theList, theValue):
|
def _disableComboItem(self, theList, theValue):
|
||||||
|
"""Disable a list item in the combo box.
|
||||||
|
"""
|
||||||
theIdx = theList.findData(theValue)
|
theIdx = theList.findData(theValue)
|
||||||
theModel = theList.model()
|
theModel = theList.model()
|
||||||
anItem = theModel.item(1)
|
anItem = theModel.item(1)
|
||||||
@@ -719,6 +727,8 @@ class GuiConfigEditEditingTab(QWidget):
|
|||||||
return theModel
|
return theModel
|
||||||
|
|
||||||
def _doUpdateSpellTool(self, currIdx):
|
def _doUpdateSpellTool(self, currIdx):
|
||||||
|
"""Update the list of dictionaries based on spell tool selected.
|
||||||
|
"""
|
||||||
spellTool = self.spellToolList.currentData()
|
spellTool = self.spellToolList.currentData()
|
||||||
self._updateLanguageList(spellTool)
|
self._updateLanguageList(spellTool)
|
||||||
return
|
return
|
||||||
@@ -903,7 +913,8 @@ class GuiConfigEditAutoReplaceTab(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def saveValues(self):
|
def saveValues(self):
|
||||||
|
"""Save the values set for this tab.
|
||||||
|
"""
|
||||||
validEntries = True
|
validEntries = True
|
||||||
needsRestart = False
|
needsRestart = False
|
||||||
|
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ class GuiProjectLoad(QDialog):
|
|||||||
"""
|
"""
|
||||||
logger.verbose("GuiProjectLoad open button clicked")
|
logger.verbose("GuiProjectLoad open button clicked")
|
||||||
self._saveDialogState()
|
self._saveDialogState()
|
||||||
|
|
||||||
selItems = self.listBox.selectedItems()
|
selItems = self.listBox.selectedItems()
|
||||||
if selItems:
|
if selItems:
|
||||||
self.openPath = selItems[0].data(self.C_NAME, Qt.UserRole)
|
self.openPath = selItems[0].data(self.C_NAME, Qt.UserRole)
|
||||||
@@ -160,6 +161,7 @@ class GuiProjectLoad(QDialog):
|
|||||||
else:
|
else:
|
||||||
self.openPath = None
|
self.openPath = None
|
||||||
self.openState = self.NONE_STATE
|
self.openState = self.NONE_STATE
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _doSelectRecent(self):
|
def _doSelectRecent(self):
|
||||||
@@ -189,6 +191,7 @@ class GuiProjectLoad(QDialog):
|
|||||||
self.openPath = thePath
|
self.openPath = thePath
|
||||||
self.openState = self.OPEN_STATE
|
self.openState = self.OPEN_STATE
|
||||||
self.accept()
|
self.accept()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _doClose(self):
|
def _doClose(self):
|
||||||
|
|||||||
+44
-9
@@ -97,6 +97,7 @@ class GuiProjectSettings(PagedDialog):
|
|||||||
bookTitle = self.tabMain.editTitle.text()
|
bookTitle = self.tabMain.editTitle.text()
|
||||||
bookAuthors = self.tabMain.editAuthors.toPlainText()
|
bookAuthors = self.tabMain.editAuthors.toPlainText()
|
||||||
doBackup = not self.tabMain.doBackup.isChecked()
|
doBackup = not self.tabMain.doBackup.isChecked()
|
||||||
|
|
||||||
self.theProject.setProjectName(projName)
|
self.theProject.setProjectName(projName)
|
||||||
self.theProject.setBookTitle(bookTitle)
|
self.theProject.setBookTitle(bookTitle)
|
||||||
self.theProject.setBookAuthors(bookAuthors)
|
self.theProject.setBookAuthors(bookAuthors)
|
||||||
@@ -105,11 +106,14 @@ class GuiProjectSettings(PagedDialog):
|
|||||||
if self.tabStatus.colChanged:
|
if self.tabStatus.colChanged:
|
||||||
statusCol = self.tabStatus.getNewList()
|
statusCol = self.tabStatus.getNewList()
|
||||||
self.theProject.setStatusColours(statusCol)
|
self.theProject.setStatusColours(statusCol)
|
||||||
|
|
||||||
if self.tabImport.colChanged:
|
if self.tabImport.colChanged:
|
||||||
importCol = self.tabImport.getNewList()
|
importCol = self.tabImport.getNewList()
|
||||||
self.theProject.setImportColours(importCol)
|
self.theProject.setImportColours(importCol)
|
||||||
|
|
||||||
if self.tabStatus.colChanged or self.tabImport.colChanged:
|
if self.tabStatus.colChanged or self.tabImport.colChanged:
|
||||||
self.theParent.rebuildTree()
|
self.theParent.rebuildTree()
|
||||||
|
|
||||||
if self.tabReplace.arChanged:
|
if self.tabReplace.arChanged:
|
||||||
newList = self.tabReplace.getNewList()
|
newList = self.tabReplace.getNewList()
|
||||||
self.theProject.setAutoReplace(newList)
|
self.theProject.setAutoReplace(newList)
|
||||||
@@ -119,7 +123,7 @@ class GuiProjectSettings(PagedDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _doClose(self):
|
def _doClose(self):
|
||||||
"""Close the dialog.
|
"""Save settings and close the dialog.
|
||||||
"""
|
"""
|
||||||
winWidth = self.mainConf.rpxInt(self.width())
|
winWidth = self.mainConf.rpxInt(self.width())
|
||||||
winHeight = self.mainConf.rpxInt(self.height())
|
winHeight = self.mainConf.rpxInt(self.height())
|
||||||
@@ -372,6 +376,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _selectColour(self):
|
def _selectColour(self):
|
||||||
|
"""Open a dialog to select the status icon colour.
|
||||||
|
"""
|
||||||
logger.verbose("Item colour button clicked")
|
logger.verbose("Item colour button clicked")
|
||||||
if self.selColour is not None:
|
if self.selColour is not None:
|
||||||
newCol = QColorDialog.getColor(
|
newCol = QColorDialog.getColor(
|
||||||
@@ -386,6 +392,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _newItem(self):
|
def _newItem(self):
|
||||||
|
"""Create a new status item.
|
||||||
|
"""
|
||||||
logger.verbose("New item button clicked")
|
logger.verbose("New item button clicked")
|
||||||
newItem = self._addItem("New Item", (0, 0, 0), None, 0)
|
newItem = self._addItem("New Item", (0, 0, 0), None, 0)
|
||||||
newItem.setBackground(QBrush(QColor(0, 255, 0, 80)))
|
newItem.setBackground(QBrush(QColor(0, 255, 0, 80)))
|
||||||
@@ -393,6 +401,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _delItem(self):
|
def _delItem(self):
|
||||||
|
"""Delete a status item.
|
||||||
|
"""
|
||||||
logger.verbose("Delete item button clicked")
|
logger.verbose("Delete item button clicked")
|
||||||
selItem = self._getSelectedItem()
|
selItem = self._getSelectedItem()
|
||||||
if selItem is not None:
|
if selItem is not None:
|
||||||
@@ -408,6 +418,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _saveItem(self):
|
def _saveItem(self):
|
||||||
|
"""Save changes made to a status item.
|
||||||
|
"""
|
||||||
logger.verbose("Save item button clicked")
|
logger.verbose("Save item button clicked")
|
||||||
selItem = self._getSelectedItem()
|
selItem = self._getSelectedItem()
|
||||||
iRow = self.listBox.row(selItem)
|
iRow = self.listBox.row(selItem)
|
||||||
@@ -427,6 +439,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _addItem(self, iName, iCol, oName, nUse):
|
def _addItem(self, iName, iCol, oName, nUse):
|
||||||
|
"""Add a status item to the list.
|
||||||
|
"""
|
||||||
newIcon = QPixmap(self.iPx, self.iPx)
|
newIcon = QPixmap(self.iPx, self.iPx)
|
||||||
newIcon.fill(QColor(*iCol))
|
newIcon.fill(QColor(*iCol))
|
||||||
newItem = QListWidgetItem()
|
newItem = QListWidgetItem()
|
||||||
@@ -439,11 +453,14 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
return newItem
|
return newItem
|
||||||
|
|
||||||
def _selectedItem(self):
|
def _selectedItem(self):
|
||||||
|
"""Extract the info of a selected item and populate the settings
|
||||||
|
boxes and button.
|
||||||
|
"""
|
||||||
logger.verbose("Item selected")
|
logger.verbose("Item selected")
|
||||||
selItem = self._getSelectedItem()
|
selItem = self._getSelectedItem()
|
||||||
if selItem is not None:
|
if selItem is not None:
|
||||||
selIdx = selItem.data(Qt.UserRole)
|
selIdx = selItem.data(Qt.UserRole)
|
||||||
selVal = self.colData[selIdx]
|
selVal = self.colData[selIdx]
|
||||||
self.selColour = QColor(selVal[1], selVal[2], selVal[3])
|
self.selColour = QColor(selVal[1], selVal[2], selVal[3])
|
||||||
newIcon = QPixmap(self.iPx, self.iPx)
|
newIcon = QPixmap(self.iPx, self.iPx)
|
||||||
newIcon.fill(self.selColour)
|
newIcon.fill(self.selColour)
|
||||||
@@ -459,6 +476,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _getSelectedItem(self):
|
def _getSelectedItem(self):
|
||||||
|
"""Get the currently selected item.
|
||||||
|
"""
|
||||||
selItem = self.listBox.selectedItems()
|
selItem = self.listBox.selectedItems()
|
||||||
if len(selItem) == 0:
|
if len(selItem) == 0:
|
||||||
return None
|
return None
|
||||||
@@ -467,6 +486,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def _rowsMoved(self):
|
def _rowsMoved(self):
|
||||||
|
"""A row has been moved, so sett the changed flag.
|
||||||
|
"""
|
||||||
logger.verbose("A drag move event occurred")
|
logger.verbose("A drag move event occurred")
|
||||||
self.colChanged = True
|
self.colChanged = True
|
||||||
return
|
return
|
||||||
@@ -506,9 +527,9 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
|
|
||||||
self.editKey = QLineEdit()
|
self.editKey = QLineEdit()
|
||||||
self.editValue = QLineEdit()
|
self.editValue = QLineEdit()
|
||||||
self.saveButton = QPushButton(self.theTheme.getIcon("done"),"")
|
self.saveButton = QPushButton(self.theTheme.getIcon("done"), "")
|
||||||
self.addButton = QPushButton(self.theTheme.getIcon("add"),"")
|
self.addButton = QPushButton(self.theTheme.getIcon("add"), "")
|
||||||
self.delButton = QPushButton(self.theTheme.getIcon("remove"),"")
|
self.delButton = QPushButton(self.theTheme.getIcon("remove"), "")
|
||||||
self.saveButton.setToolTip("Save entry")
|
self.saveButton.setToolTip("Save entry")
|
||||||
self.addButton.setToolTip("Add new entry")
|
self.addButton.setToolTip("Add new entry")
|
||||||
self.delButton.setToolTip("Delete selected entry")
|
self.delButton.setToolTip("Delete selected entry")
|
||||||
@@ -536,11 +557,13 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def getNewList(self):
|
def getNewList(self):
|
||||||
|
"""Extract the list from the widget.
|
||||||
|
"""
|
||||||
newList = {}
|
newList = {}
|
||||||
for n in range(self.listBox.topLevelItemCount()):
|
for n in range(self.listBox.topLevelItemCount()):
|
||||||
tItem = self.listBox.topLevelItem(n)
|
tItem = self.listBox.topLevelItem(n)
|
||||||
aKey = self._stripNotAllowed(tItem.text(0))
|
aKey = self._stripNotAllowed(tItem.text(0))
|
||||||
aVal = tItem.text(1)
|
aVal = tItem.text(1)
|
||||||
if len(aKey) > 0:
|
if len(aKey) > 0:
|
||||||
newList[aKey] = aVal
|
newList[aKey] = aVal
|
||||||
return newList
|
return newList
|
||||||
@@ -550,6 +573,9 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _selectedItem(self):
|
def _selectedItem(self):
|
||||||
|
"""Extract the details from the selected item and populate the
|
||||||
|
edit form.
|
||||||
|
"""
|
||||||
selItem = self._getSelectedItem()
|
selItem = self._getSelectedItem()
|
||||||
if selItem is None:
|
if selItem is None:
|
||||||
return False
|
return False
|
||||||
@@ -564,7 +590,8 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _saveEntry(self):
|
def _saveEntry(self):
|
||||||
|
"""Save the form data into the list widget.
|
||||||
|
"""
|
||||||
selItem = self._getSelectedItem()
|
selItem = self._getSelectedItem()
|
||||||
if selItem is None:
|
if selItem is None:
|
||||||
return False
|
return False
|
||||||
@@ -586,6 +613,8 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _addEntry(self):
|
def _addEntry(self):
|
||||||
|
"""Add a new list entry.
|
||||||
|
"""
|
||||||
saveKey = "<keyword%d>" % (self.listBox.topLevelItemCount() + 1)
|
saveKey = "<keyword%d>" % (self.listBox.topLevelItemCount() + 1)
|
||||||
newVal = ""
|
newVal = ""
|
||||||
newItem = QTreeWidgetItem([saveKey, newVal])
|
newItem = QTreeWidgetItem([saveKey, newVal])
|
||||||
@@ -593,6 +622,8 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _delEntry(self):
|
def _delEntry(self):
|
||||||
|
"""Delete the selected entry.
|
||||||
|
"""
|
||||||
selItem = self._getSelectedItem()
|
selItem = self._getSelectedItem()
|
||||||
if selItem is None:
|
if selItem is None:
|
||||||
return False
|
return False
|
||||||
@@ -601,12 +632,16 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _getSelectedItem(self):
|
def _getSelectedItem(self):
|
||||||
|
"""Extract the currently selected item.
|
||||||
|
"""
|
||||||
selItem = self.listBox.selectedItems()
|
selItem = self.listBox.selectedItems()
|
||||||
if len(selItem) == 0:
|
if len(selItem) == 0:
|
||||||
return None
|
return None
|
||||||
return selItem[0]
|
return selItem[0]
|
||||||
|
|
||||||
def _stripNotAllowed(self, theKey):
|
def _stripNotAllowed(self, theKey):
|
||||||
|
"""Clean up the replace key string.
|
||||||
|
"""
|
||||||
retKey = ""
|
retKey = ""
|
||||||
for c in theKey:
|
for c in theKey:
|
||||||
if c.isalnum():
|
if c.isalnum():
|
||||||
|
|||||||
+30
-4
@@ -30,15 +30,15 @@ import logging
|
|||||||
import nw
|
import nw
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt, QSize
|
||||||
from PyQt5.QtGui import QFont, QColor, QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMessageBox,
|
qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMessageBox,
|
||||||
QHeaderView, QMenu, QAction
|
QMenu, QAction
|
||||||
)
|
)
|
||||||
|
|
||||||
from nw.core import NWDoc
|
from nw.core import NWDoc
|
||||||
from nw.constants import (
|
from nw.constants import (
|
||||||
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert, nwUnicode
|
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -90,7 +90,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
# for some fonts like the Ubuntu font.
|
# for some fonts like the Ubuntu font.
|
||||||
treeHeader = self.header()
|
treeHeader = self.header()
|
||||||
treeHeader.setStretchLastSection(True)
|
treeHeader.setStretchLastSection(True)
|
||||||
treeHeader.setMinimumSectionSize(iPx+6)
|
treeHeader.setMinimumSectionSize(iPx + 6)
|
||||||
|
|
||||||
# Allow Move by Drag & Drop
|
# Allow Move by Drag & Drop
|
||||||
self.setDragEnabled(True)
|
self.setDragEnabled(True)
|
||||||
@@ -237,6 +237,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
has focus. This also applies when the menu is used.
|
has focus. This also applies when the menu is used.
|
||||||
"""
|
"""
|
||||||
if qApp.focusWidget() == self and self.theParent.hasProject:
|
if qApp.focusWidget() == self and self.theParent.hasProject:
|
||||||
|
|
||||||
tHandle = self.getSelectedHandle()
|
tHandle = self.getSelectedHandle()
|
||||||
tItem = self._getTreeItem(tHandle)
|
tItem = self._getTreeItem(tHandle)
|
||||||
pItem = tItem.parent()
|
pItem = tItem.parent()
|
||||||
@@ -248,6 +249,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
return False
|
return False
|
||||||
cItem = self.takeTopLevelItem(tIndex)
|
cItem = self.takeTopLevelItem(tIndex)
|
||||||
self.insertTopLevelItem(nIndex, cItem)
|
self.insertTopLevelItem(nIndex, cItem)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
tIndex = pItem.indexOfChild(tItem)
|
tIndex = pItem.indexOfChild(tItem)
|
||||||
nChild = pItem.childCount()
|
nChild = pItem.childCount()
|
||||||
@@ -256,11 +258,14 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
return False
|
return False
|
||||||
cItem = pItem.takeChild(tIndex)
|
cItem = pItem.takeChild(tIndex)
|
||||||
pItem.insertChild(nIndex, cItem)
|
pItem.insertChild(nIndex, cItem)
|
||||||
|
|
||||||
self.clearSelection()
|
self.clearSelection()
|
||||||
cItem.setSelected(True)
|
cItem.setSelected(True)
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def saveTreeOrder(self):
|
def saveTreeOrder(self):
|
||||||
@@ -516,8 +521,10 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
for i in range(pItem.childCount()):
|
for i in range(pItem.childCount()):
|
||||||
pCount += int(pItem.child(i).text(self.C_COUNT))
|
pCount += int(pItem.child(i).text(self.C_COUNT))
|
||||||
pHandle = pItem.data(self.C_NAME, Qt.UserRole)
|
pHandle = pItem.data(self.C_NAME, Qt.UserRole)
|
||||||
|
|
||||||
if not nDepth > 200 and pHandle != "":
|
if not nDepth > 200 and pHandle != "":
|
||||||
self.propagateCount(pHandle, pCount, nDepth+1)
|
self.propagateCount(pHandle, pCount, nDepth+1)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def projectWordCount(self):
|
def projectWordCount(self):
|
||||||
@@ -533,9 +540,11 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
if tItem == self.orphRoot:
|
if tItem == self.orphRoot:
|
||||||
continue
|
continue
|
||||||
nWords += int(tItem.text(self.C_COUNT))
|
nWords += int(tItem.text(self.C_COUNT))
|
||||||
|
|
||||||
self.theProject.setProjectWordCount(nWords)
|
self.theProject.setProjectWordCount(nWords)
|
||||||
sWords = self.theProject.getSessionWordCount()
|
sWords = self.theProject.getSessionWordCount()
|
||||||
self.theParent.statusBar.setStats(nWords,sWords)
|
self.theParent.statusBar.setStats(nWords,sWords)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def buildTree(self):
|
def buildTree(self):
|
||||||
@@ -547,9 +556,11 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
logger.debug("Building project tree ...")
|
logger.debug("Building project tree ...")
|
||||||
self.clear()
|
self.clear()
|
||||||
iCount = 0
|
iCount = 0
|
||||||
|
|
||||||
for nwItem in self.theProject.getProjectItems():
|
for nwItem in self.theProject.getProjectItems():
|
||||||
iCount += 1
|
iCount += 1
|
||||||
self._addTreeItem(nwItem)
|
self._addTreeItem(nwItem)
|
||||||
|
|
||||||
logger.debug("%d items added to project tree" % iCount)
|
logger.debug("%d items added to project tree" % iCount)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -558,10 +569,13 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
selected, return the first.
|
selected, return the first.
|
||||||
"""
|
"""
|
||||||
selItem = self.selectedItems()
|
selItem = self.selectedItems()
|
||||||
|
|
||||||
if len(selItem) == 0:
|
if len(selItem) == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if isinstance(selItem[0], QTreeWidgetItem):
|
if isinstance(selItem[0], QTreeWidgetItem):
|
||||||
return selItem[0].data(self.C_NAME, Qt.UserRole)
|
return selItem[0].data(self.C_NAME, Qt.UserRole)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getSelectedHandles(self):
|
def getSelectedHandles(self):
|
||||||
@@ -572,6 +586,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
for n in range(len(selItems)):
|
for n in range(len(selItems)):
|
||||||
if isinstance(selItems[n], QTreeWidgetItem):
|
if isinstance(selItems[n], QTreeWidgetItem):
|
||||||
selHandles.append(selItems[n].data(self.C_NAME, Qt.UserRole))
|
selHandles.append(selItems[n].data(self.C_NAME, Qt.UserRole))
|
||||||
|
|
||||||
return selHandles
|
return selHandles
|
||||||
|
|
||||||
def setSelectedHandle(self, tHandle, doScroll=False):
|
def setSelectedHandle(self, tHandle, doScroll=False):
|
||||||
@@ -580,12 +595,14 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
if tHandle in self.theMap:
|
if tHandle in self.theMap:
|
||||||
self.clearSelection()
|
self.clearSelection()
|
||||||
self.theMap[tHandle].setSelected(True)
|
self.theMap[tHandle].setSelected(True)
|
||||||
|
|
||||||
selItems = self.selectedIndexes()
|
selItems = self.selectedIndexes()
|
||||||
if selItems and doScroll:
|
if selItems and doScroll:
|
||||||
self.scrollTo(
|
self.scrollTo(
|
||||||
selItems[0], QAbstractItemView.PositionAtCenter
|
selItems[0], QAbstractItemView.PositionAtCenter
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -601,9 +618,11 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
tHandle = selItem.data(self.C_NAME, Qt.UserRole)
|
tHandle = selItem.data(self.C_NAME, Qt.UserRole)
|
||||||
tItem = self.theProject.projTree[tHandle]
|
tItem = self.theProject.projTree[tHandle]
|
||||||
self.setSelectedHandle(tHandle) # Just to be safe
|
self.setSelectedHandle(tHandle) # Just to be safe
|
||||||
|
|
||||||
if self.ctxMenu.filterActions(tItem):
|
if self.ctxMenu.filterActions(tItem):
|
||||||
# Only open menu if any actions remain after filter
|
# Only open menu if any actions remain after filter
|
||||||
self.ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
|
self.ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -615,9 +634,11 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
mouse in a blank area of the tree view.
|
mouse in a blank area of the tree view.
|
||||||
"""
|
"""
|
||||||
QTreeWidget.mousePressEvent(self, theEvent)
|
QTreeWidget.mousePressEvent(self, theEvent)
|
||||||
|
|
||||||
selItem = self.indexAt(theEvent.pos())
|
selItem = self.indexAt(theEvent.pos())
|
||||||
if not selItem.isValid():
|
if not selItem.isValid():
|
||||||
self.clearSelection()
|
self.clearSelection()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def dropEvent(self, theEvent):
|
def dropEvent(self, theEvent):
|
||||||
@@ -766,6 +787,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
trashHandle = self.theProject.trashFolder()
|
trashHandle = self.theProject.trashFolder()
|
||||||
if trashHandle is None:
|
if trashHandle is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
trItem = self._getTreeItem(trashHandle)
|
trItem = self._getTreeItem(trashHandle)
|
||||||
if trItem is None:
|
if trItem is None:
|
||||||
trItem = self._addTreeItem(
|
trItem = self._addTreeItem(
|
||||||
@@ -773,6 +795,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
)
|
)
|
||||||
trItem.setExpanded(True)
|
trItem.setExpanded(True)
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
|
|
||||||
return trItem
|
return trItem
|
||||||
|
|
||||||
def _addOrphanedRoot(self):
|
def _addOrphanedRoot(self):
|
||||||
@@ -790,6 +813,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
newItem.setExpanded(True)
|
newItem.setExpanded(True)
|
||||||
newItem.setData(self.C_NAME, Qt.UserRole, "")
|
newItem.setData(self.C_NAME, Qt.UserRole, "")
|
||||||
newItem.setIcon(self.C_NAME, self.theTheme.getIcon("proj_orphan"))
|
newItem.setIcon(self.C_NAME, self.theTheme.getIcon("proj_orphan"))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _cleanOrphanedRoot(self):
|
def _cleanOrphanedRoot(self):
|
||||||
@@ -834,10 +858,12 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
if trItemP is None:
|
if trItemP is None:
|
||||||
logger.error("Failed to find new parent item of %s" % tHandle)
|
logger.error("Failed to find new parent item of %s" % tHandle)
|
||||||
return
|
return
|
||||||
|
|
||||||
pHandle = trItemP.data(self.C_NAME, Qt.UserRole)
|
pHandle = trItemP.data(self.C_NAME, Qt.UserRole)
|
||||||
nwItemS.setParent(pHandle)
|
nwItemS.setParent(pHandle)
|
||||||
self.setTreeItemValues(tHandle)
|
self.setTreeItemValues(tHandle)
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _setTreeChanged(self, theState):
|
def _setTreeChanged(self, theState):
|
||||||
|
|||||||
+3
-3
@@ -30,8 +30,8 @@ import nw
|
|||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
from PyQt5.QtGui import QColor, QPixmap, QFont, QPainter
|
from PyQt5.QtGui import QColor, QPainter
|
||||||
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
|
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
|
||||||
|
|
||||||
from nw.core import NWSpellCheck
|
from nw.core import NWSpellCheck
|
||||||
@@ -264,7 +264,7 @@ class StatusLED(QAbstractButton):
|
|||||||
qPaint.setPen(qPalette.dark().color())
|
qPaint.setPen(qPalette.dark().color())
|
||||||
qPaint.setBrush(self._theCol)
|
qPaint.setBrush(self._theCol)
|
||||||
qPaint.setOpacity(1.0)
|
qPaint.setOpacity(1.0)
|
||||||
qPaint.drawEllipse(1, 1, self.width()-2, self.height()-2)
|
qPaint.drawEllipse(1, 1, self.width() - 2, self.height() - 2)
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class StatusLED
|
# END Class StatusLED
|
||||||
|
|||||||
+56
-53
@@ -77,11 +77,11 @@ class GuiTheme:
|
|||||||
self.themeLicenseUrl = ""
|
self.themeLicenseUrl = ""
|
||||||
|
|
||||||
## GUI
|
## GUI
|
||||||
self.treeWCount = [ 0, 0, 0]
|
self.treeWCount = [ 0, 0, 0]
|
||||||
self.statNone = [120,120,120]
|
self.statNone = [120, 120, 120]
|
||||||
self.statUnsaved = [120,120, 40]
|
self.statUnsaved = [120, 120, 40]
|
||||||
self.statSaved = [ 40,120, 0]
|
self.statSaved = [ 40, 120, 0]
|
||||||
self.helpText = [ 0, 0, 0]
|
self.helpText = [ 0, 0, 0]
|
||||||
|
|
||||||
# Loaded Syntax Settings
|
# Loaded Syntax Settings
|
||||||
|
|
||||||
@@ -95,22 +95,22 @@ class GuiTheme:
|
|||||||
self.syntaxLicenseUrl = ""
|
self.syntaxLicenseUrl = ""
|
||||||
|
|
||||||
## Colours
|
## Colours
|
||||||
self.colBack = [255,255,255]
|
self.colBack = [255, 255, 255]
|
||||||
self.colText = [ 0, 0, 0]
|
self.colText = [ 0, 0, 0]
|
||||||
self.colLink = [ 0, 0, 0]
|
self.colLink = [ 0, 0, 0]
|
||||||
self.colHead = [ 0, 0, 0]
|
self.colHead = [ 0, 0, 0]
|
||||||
self.colHeadH = [ 0, 0, 0]
|
self.colHeadH = [ 0, 0, 0]
|
||||||
self.colEmph = [ 0, 0, 0]
|
self.colEmph = [ 0, 0, 0]
|
||||||
self.colDialN = [ 0, 0, 0]
|
self.colDialN = [ 0, 0, 0]
|
||||||
self.colDialD = [ 0, 0, 0]
|
self.colDialD = [ 0, 0, 0]
|
||||||
self.colDialS = [ 0, 0, 0]
|
self.colDialS = [ 0, 0, 0]
|
||||||
self.colComm = [ 0, 0, 0]
|
self.colComm = [ 0, 0, 0]
|
||||||
self.colKey = [ 0, 0, 0]
|
self.colKey = [ 0, 0, 0]
|
||||||
self.colVal = [ 0, 0, 0]
|
self.colVal = [ 0, 0, 0]
|
||||||
self.colSpell = [ 0, 0, 0]
|
self.colSpell = [ 0, 0, 0]
|
||||||
self.colTagErr = [ 0, 0, 0]
|
self.colTagErr = [ 0, 0, 0]
|
||||||
self.colRepTag = [ 0, 0, 0]
|
self.colRepTag = [ 0, 0, 0]
|
||||||
self.colMod = [ 0, 0, 0]
|
self.colMod = [ 0, 0, 0]
|
||||||
|
|
||||||
# Changeable Settings
|
# Changeable Settings
|
||||||
self.guiTheme = None
|
self.guiTheme = None
|
||||||
@@ -144,9 +144,9 @@ class GuiTheme:
|
|||||||
qMetric = QFontMetrics(self.guiFont)
|
qMetric = QFontMetrics(self.guiFont)
|
||||||
self.fontPointSize = self.guiFont.pointSizeF()
|
self.fontPointSize = self.guiFont.pointSizeF()
|
||||||
self.fontPixelSize = int(round(qMetric.height()))
|
self.fontPixelSize = int(round(qMetric.height()))
|
||||||
self.baseIconSize = int(round(qMetric.ascent()))
|
self.baseIconSize = int(round(qMetric.ascent()))
|
||||||
self.textNHeight = qMetric.boundingRect("N").height()
|
self.textNHeight = qMetric.boundingRect("N").height()
|
||||||
self.textNWidth = qMetric.boundingRect("N").width()
|
self.textNWidth= qMetric.boundingRect("N").width()
|
||||||
|
|
||||||
logger.verbose("GUI Font Family: %s" % self.guiFont.family())
|
logger.verbose("GUI Font Family: %s" % self.guiFont.family())
|
||||||
logger.verbose("GUI Font Point Size: %.2f" % self.fontPointSize)
|
logger.verbose("GUI Font Point Size: %.2f" % self.fontPointSize)
|
||||||
@@ -223,10 +223,10 @@ class GuiTheme:
|
|||||||
self.guiTheme = self.mainConf.guiTheme
|
self.guiTheme = self.mainConf.guiTheme
|
||||||
self.guiSyntax = self.mainConf.guiSyntax
|
self.guiSyntax = self.mainConf.guiSyntax
|
||||||
self.themeRoot = self.mainConf.themeRoot
|
self.themeRoot = self.mainConf.themeRoot
|
||||||
self.themePath = path.join(self.mainConf.themeRoot,self.guiPath,self.guiTheme)
|
self.themePath = path.join(self.mainConf.themeRoot, self.guiPath, self.guiTheme)
|
||||||
self.syntaxFile = path.join(self.themeRoot,self.syntaxPath,self.guiSyntax+".conf")
|
self.syntaxFile = path.join(self.themeRoot, self.syntaxPath, self.guiSyntax+".conf")
|
||||||
self.confFile = path.join(self.themePath,self.confName)
|
self.confFile = path.join(self.themePath, self.confName)
|
||||||
self.cssFile = path.join(self.themePath,self.cssName)
|
self.cssFile = path.join(self.themePath, self.cssName)
|
||||||
|
|
||||||
self.loadTheme()
|
self.loadTheme()
|
||||||
self.loadSyntax()
|
self.loadSyntax()
|
||||||
@@ -256,7 +256,7 @@ class GuiTheme:
|
|||||||
cssData = ""
|
cssData = ""
|
||||||
try:
|
try:
|
||||||
if path.isfile(self.cssFile):
|
if path.isfile(self.cssFile):
|
||||||
with open(self.cssFile,mode="r",encoding="utf8") as inFile:
|
with open(self.cssFile, mode="r", encoding="utf8") as inFile:
|
||||||
cssData = inFile.read()
|
cssData = inFile.read()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Could not load theme css file")
|
logger.error("Could not load theme css file")
|
||||||
@@ -329,13 +329,13 @@ class GuiTheme:
|
|||||||
## Main
|
## Main
|
||||||
cnfSec = "Main"
|
cnfSec = "Main"
|
||||||
if confParser.has_section(cnfSec):
|
if confParser.has_section(cnfSec):
|
||||||
self.syntaxName = self._parseLine( confParser, cnfSec, "name", "")
|
self.syntaxName = self._parseLine(confParser, cnfSec, "name", "")
|
||||||
self.syntaxDescription = self._parseLine( confParser, cnfSec, "description", "")
|
self.syntaxDescription = self._parseLine(confParser, cnfSec, "description", "")
|
||||||
self.syntaxAuthor = self._parseLine( confParser, cnfSec, "author", "")
|
self.syntaxAuthor = self._parseLine(confParser, cnfSec, "author", "")
|
||||||
self.syntaxCredit = self._parseLine( confParser, cnfSec, "credit", "")
|
self.syntaxCredit = self._parseLine(confParser, cnfSec, "credit", "")
|
||||||
self.syntaxUrl = self._parseLine( confParser, cnfSec, "url", "")
|
self.syntaxUrl = self._parseLine(confParser, cnfSec, "url", "")
|
||||||
self.syntaxLicense = self._parseLine( confParser, cnfSec, "license", "")
|
self.syntaxLicense = self._parseLine(confParser, cnfSec, "license", "")
|
||||||
self.syntaxLicenseUrl = self._parseLine( confParser, cnfSec, "licenseurl", "")
|
self.syntaxLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
cnfSec = "Syntax"
|
cnfSec = "Syntax"
|
||||||
@@ -376,7 +376,7 @@ class GuiTheme:
|
|||||||
confParser.read_file(inFile)
|
confParser.read_file(inFile)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
["Could not load theme config file.",str(e)], nwAlert.ERROR
|
["Could not load theme config file.", str(e)], nwAlert.ERROR
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
themeName = ""
|
themeName = ""
|
||||||
@@ -409,7 +409,7 @@ class GuiTheme:
|
|||||||
confParser.read_file(inFile)
|
confParser.read_file(inFile)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
["Could not load syntax file.",str(e)], nwAlert.ERROR
|
["Could not load syntax file.", str(e)], nwAlert.ERROR
|
||||||
)
|
)
|
||||||
return []
|
return []
|
||||||
syntaxName = ""
|
syntaxName = ""
|
||||||
@@ -429,8 +429,10 @@ class GuiTheme:
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _loadColour(self, confParser, cnfSec, cnfName):
|
def _loadColour(self, confParser, cnfSec, cnfName):
|
||||||
|
"""Load a colour value from a config string.
|
||||||
|
"""
|
||||||
if confParser.has_option(cnfSec,cnfName):
|
if confParser.has_option(cnfSec,cnfName):
|
||||||
inData = confParser.get(cnfSec,cnfName).split(",")
|
inData = confParser.get(cnfSec,cnfName).split(",")
|
||||||
outData = []
|
outData = []
|
||||||
try:
|
try:
|
||||||
outData.append(int(inData[0]))
|
outData.append(int(inData[0]))
|
||||||
@@ -438,16 +440,18 @@ class GuiTheme:
|
|||||||
outData.append(int(inData[2]))
|
outData.append(int(inData[2]))
|
||||||
except:
|
except:
|
||||||
logger.error("Could not load theme colours for '%s' from config file" % cnfName)
|
logger.error("Could not load theme colours for '%s' from config file" % cnfName)
|
||||||
outData = [0,0,0]
|
outData = [0, 0, 0]
|
||||||
else:
|
else:
|
||||||
logger.warning("Could not find theme colours for '%s' in config file" % cnfName)
|
logger.warning("Could not find theme colours for '%s' in config file" % cnfName)
|
||||||
outData = [0,0,0]
|
outData = [0, 0, 0]
|
||||||
return outData
|
return outData
|
||||||
|
|
||||||
def _setPalette(self, confParser, cnfSec, cnfName, paletteVal):
|
def _setPalette(self, confParser, cnfSec, cnfName, paletteVal):
|
||||||
|
"""Set a palette colour value from a config string.
|
||||||
|
"""
|
||||||
readCol = []
|
readCol = []
|
||||||
if confParser.has_option(cnfSec,cnfName):
|
if confParser.has_option(cnfSec,cnfName):
|
||||||
inData = confParser.get(cnfSec,cnfName).split(",")
|
inData = confParser.get(cnfSec,cnfName).split(",")
|
||||||
try:
|
try:
|
||||||
readCol.append(int(inData[0]))
|
readCol.append(int(inData[0]))
|
||||||
readCol.append(int(inData[1]))
|
readCol.append(int(inData[1]))
|
||||||
@@ -547,8 +551,8 @@ class GuiIcons:
|
|||||||
"reference" : (None, None),
|
"reference" : (None, None),
|
||||||
|
|
||||||
## Switches
|
## Switches
|
||||||
"sticky-on" : (None, None),
|
"sticky-on" : (None, None),
|
||||||
"sticky-off" : (None, None),
|
"sticky-off" : (None, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
DECO_MAP = {
|
DECO_MAP = {
|
||||||
@@ -615,13 +619,13 @@ class GuiIcons:
|
|||||||
## Main
|
## Main
|
||||||
cnfSec = "Main"
|
cnfSec = "Main"
|
||||||
if confParser.has_section(cnfSec):
|
if confParser.has_section(cnfSec):
|
||||||
self.themeName = self._parseLine( confParser, cnfSec, "name", "")
|
self.themeName = self._parseLine(confParser, cnfSec, "name", "")
|
||||||
self.themeDescription = self._parseLine( confParser, cnfSec, "description", "")
|
self.themeDescription = self._parseLine(confParser, cnfSec, "description", "")
|
||||||
self.themeAuthor = self._parseLine( confParser, cnfSec, "author", "")
|
self.themeAuthor = self._parseLine(confParser, cnfSec, "author", "")
|
||||||
self.themeCredit = self._parseLine( confParser, cnfSec, "credit", "")
|
self.themeCredit = self._parseLine(confParser, cnfSec, "credit", "")
|
||||||
self.themeUrl = self._parseLine( confParser, cnfSec, "url", "")
|
self.themeUrl = self._parseLine(confParser, cnfSec, "url", "")
|
||||||
self.themeLicense = self._parseLine( confParser, cnfSec, "license", "")
|
self.themeLicense = self._parseLine(confParser, cnfSec, "license", "")
|
||||||
self.themeLicenseUrl = self._parseLine( confParser, cnfSec, "licenseurl", "")
|
self.themeLicenseUrl = self._parseLine(confParser, cnfSec, "licenseurl", "")
|
||||||
|
|
||||||
## Palette
|
## Palette
|
||||||
cnfSec = "Map"
|
cnfSec = "Map"
|
||||||
@@ -705,7 +709,7 @@ class GuiIcons:
|
|||||||
confParser.read_file(inFile)
|
confParser.read_file(inFile)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
["Could not load theme config file.",str(e)], nwAlert.ERROR
|
["Could not load theme config file.", str(e)], nwAlert.ERROR
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
themeName = ""
|
themeName = ""
|
||||||
@@ -730,7 +734,6 @@ class GuiIcons:
|
|||||||
an icon exists. Prefer svg files over png files. Always returns
|
an icon exists. Prefer svg files over png files. Always returns
|
||||||
a QIcon.
|
a QIcon.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if iconKey not in self.ICON_MAP:
|
if iconKey not in self.ICON_MAP:
|
||||||
logger.error("Requested unknown icon name '%s'" % iconKey)
|
logger.error("Requested unknown icon name '%s'" % iconKey)
|
||||||
return QIcon()
|
return QIcon()
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class GuiWritingStats(QDialog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.listBox = QTreeWidget()
|
self.listBox = QTreeWidget()
|
||||||
self.listBox.setHeaderLabels(["Session Start","Length","Words","Histogram"])
|
self.listBox.setHeaderLabels(["Session Start", "Length", "Words", "Histogram"])
|
||||||
self.listBox.setIndentation(0)
|
self.listBox.setIndentation(0)
|
||||||
self.listBox.setColumnWidth(self.C_TIME, wCol0)
|
self.listBox.setColumnWidth(self.C_TIME, wCol0)
|
||||||
self.listBox.setColumnWidth(self.C_LENGTH, wCol1)
|
self.listBox.setColumnWidth(self.C_LENGTH, wCol1)
|
||||||
|
|||||||
+71
-47
@@ -46,7 +46,7 @@ from nw.gui import (
|
|||||||
GuiProjectSettings, GuiProjectTree, GuiWritingStats, GuiAbout
|
GuiProjectSettings, GuiProjectTree, GuiWritingStats, GuiAbout
|
||||||
)
|
)
|
||||||
from nw.core import NWProject, NWDoc, NWIndex
|
from nw.core import NWProject, NWDoc, NWIndex
|
||||||
from nw.constants import nwFiles, nwItemType, nwAlert
|
from nw.constants import nwItemType, nwAlert
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.tabWidget = QTabWidget()
|
self.tabWidget = QTabWidget()
|
||||||
self.tabWidget.setTabPosition(QTabWidget.East)
|
self.tabWidget.setTabPosition(QTabWidget.East)
|
||||||
self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;}")
|
self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;}")
|
||||||
self.tabWidget.addTab(self.splitDocs, "Editor")
|
self.tabWidget.addTab(self.splitDocs, "Editor")
|
||||||
self.tabWidget.addTab(self.splitOutline, "Outline")
|
self.tabWidget.addTab(self.splitOutline, "Outline")
|
||||||
self.tabWidget.currentChanged.connect(self._mainTabChanged)
|
self.tabWidget.currentChanged.connect(self._mainTabChanged)
|
||||||
|
|
||||||
@@ -139,8 +139,6 @@ class GuiMain(QMainWindow):
|
|||||||
self.splitMain.addWidget(self.tabWidget)
|
self.splitMain.addWidget(self.tabWidget)
|
||||||
self.splitMain.setSizes(self.mainConf.getMainPanePos())
|
self.splitMain.setSizes(self.mainConf.getMainPanePos())
|
||||||
|
|
||||||
self.setCentralWidget(self.splitMain)
|
|
||||||
|
|
||||||
self.idxTree = self.splitMain.indexOf(self.treePane)
|
self.idxTree = self.splitMain.indexOf(self.treePane)
|
||||||
self.idxMain = self.splitMain.indexOf(self.tabWidget)
|
self.idxMain = self.splitMain.indexOf(self.tabWidget)
|
||||||
self.idxEditor = self.splitDocs.indexOf(self.docEditor)
|
self.idxEditor = self.splitDocs.indexOf(self.docEditor)
|
||||||
@@ -167,8 +165,8 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
# Set Main Window Elements
|
# Set Main Window Elements
|
||||||
self.setMenuBar(self.mainMenu)
|
self.setMenuBar(self.mainMenu)
|
||||||
|
self.setCentralWidget(self.splitMain)
|
||||||
self.setStatusBar(self.statusBar)
|
self.setStatusBar(self.statusBar)
|
||||||
self.statusBar.setStatus("Ready")
|
|
||||||
|
|
||||||
# Finalise Initialisation
|
# Finalise Initialisation
|
||||||
##########################
|
##########################
|
||||||
@@ -222,6 +220,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.manageProjects()
|
self.manageProjects()
|
||||||
|
|
||||||
logger.debug("novelWriter is ready ...")
|
logger.debug("novelWriter is ready ...")
|
||||||
|
self.statusBar.setStatus("novelWriter is ready ...")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -348,9 +347,7 @@ class GuiMain(QMainWindow):
|
|||||||
return saveOK
|
return saveOK
|
||||||
|
|
||||||
def openProject(self, projFile):
|
def openProject(self, projFile):
|
||||||
"""Open a project. The parameter projFile is passed from the
|
"""Open a project from a projFile path.
|
||||||
open recent projects menu, and must be set to be forwarded to
|
|
||||||
the project class. Otherwise, we just return.
|
|
||||||
"""
|
"""
|
||||||
if projFile is None:
|
if projFile is None:
|
||||||
return False
|
return False
|
||||||
@@ -365,43 +362,47 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
# Try to open the project
|
# Try to open the project
|
||||||
if not self.theProject.openProject(projFile):
|
if not self.theProject.openProject(projFile):
|
||||||
if self.theProject.lockedBy is not None:
|
# The project open failed.
|
||||||
if self.mainConf.showGUI:
|
|
||||||
try:
|
|
||||||
lockDetails = (
|
|
||||||
"<br><br>The project was locked by the computer "
|
|
||||||
"'%s' (%s %s), last active on %s"
|
|
||||||
) % (
|
|
||||||
self.theProject.lockedBy[0],
|
|
||||||
self.theProject.lockedBy[1],
|
|
||||||
self.theProject.lockedBy[2],
|
|
||||||
datetime.fromtimestamp(
|
|
||||||
int(self.theProject.lockedBy[3])
|
|
||||||
).strftime("%x %X")
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
lockDetails = ""
|
|
||||||
|
|
||||||
msgBox = QMessageBox()
|
if self.theProject.lockedBy is None:
|
||||||
msgRes = msgBox.warning(
|
# The project is not locked, so failed for some other
|
||||||
self, "Project Locked", (
|
# reason handled by the project class.
|
||||||
"The project is already open by another instance of novelWriter, and "
|
|
||||||
"is therefore locked. Override lock and continue anyway?<br><br>"
|
|
||||||
"Note: If the program or the computer previously crashed, the lock "
|
|
||||||
"can safely be overridden. If, however, another instance of "
|
|
||||||
"novelWriter has the project open, overriding the lock may corrupt "
|
|
||||||
"the project, and is not recommended.%s"
|
|
||||||
) % lockDetails,
|
|
||||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
|
||||||
)
|
|
||||||
if msgRes == QMessageBox.Yes:
|
|
||||||
if not self.theProject.openProject(projFile, overrideLock=True):
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if self.mainConf.showGUI:
|
||||||
|
try:
|
||||||
|
lockDetails = (
|
||||||
|
"<br><br>The project was locked by the computer "
|
||||||
|
"'%s' (%s %s), last active on %s"
|
||||||
|
) % (
|
||||||
|
self.theProject.lockedBy[0],
|
||||||
|
self.theProject.lockedBy[1],
|
||||||
|
self.theProject.lockedBy[2],
|
||||||
|
datetime.fromtimestamp(
|
||||||
|
int(self.theProject.lockedBy[3])
|
||||||
|
).strftime("%x %X")
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
lockDetails = ""
|
||||||
|
|
||||||
|
msgBox = QMessageBox()
|
||||||
|
msgRes = msgBox.warning(
|
||||||
|
self, "Project Locked", (
|
||||||
|
"The project is already open by another instance of novelWriter, and "
|
||||||
|
"is therefore locked. Override lock and continue anyway?<br><br>"
|
||||||
|
"Note: If the program or the computer previously crashed, the lock "
|
||||||
|
"can safely be overridden. If, however, another instance of "
|
||||||
|
"novelWriter has the project open, overriding the lock may corrupt "
|
||||||
|
"the project, and is not recommended.%s"
|
||||||
|
) % lockDetails,
|
||||||
|
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||||
|
)
|
||||||
|
if msgRes == QMessageBox.Yes:
|
||||||
|
if not self.theProject.openProject(projFile, overrideLock=True):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
# Project is loaded
|
# Project is loaded
|
||||||
self.hasProject = True
|
self.hasProject = True
|
||||||
|
|
||||||
@@ -570,7 +571,7 @@ class GuiMain(QMainWindow):
|
|||||||
dlgOpt = QFileDialog.Options()
|
dlgOpt = QFileDialog.Options()
|
||||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||||
inPath = QFileDialog.getOpenFileName(
|
inPath = QFileDialog.getOpenFileName(
|
||||||
self,"Import File",lastPath,options=dlgOpt,filter=";;".join(extFilter)
|
self, "Import File", lastPath, options=dlgOpt, filter=";;".join(extFilter)
|
||||||
)
|
)
|
||||||
if inPath:
|
if inPath:
|
||||||
loadFile = inPath[0]
|
loadFile = inPath[0]
|
||||||
@@ -582,7 +583,7 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
theText = None
|
theText = None
|
||||||
try:
|
try:
|
||||||
with open(loadFile,mode="rt",encoding="utf8") as inFile:
|
with open(loadFile, mode="rt", encoding="utf8") as inFile:
|
||||||
theText = inFile.read()
|
theText = inFile.read()
|
||||||
self.mainConf.setLastPath(loadFile)
|
self.mainConf.setLastPath(loadFile)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -602,7 +603,7 @@ class GuiMain(QMainWindow):
|
|||||||
if not self.docEditor.isEmpty():
|
if not self.docEditor.isEmpty():
|
||||||
if self.mainConf.showGUI:
|
if self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(self, "Import Document",(
|
msgRes = msgBox.question(self, "Import Document", (
|
||||||
"Importing the file will overwrite the current content of the document. "
|
"Importing the file will overwrite the current content of the document. "
|
||||||
"Do you want to proceed?"
|
"Do you want to proceed?"
|
||||||
))
|
))
|
||||||
@@ -917,6 +918,8 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def setFocus(self, paneNo):
|
def setFocus(self, paneNo):
|
||||||
|
"""Switch focus to one of the three main gUi panes.
|
||||||
|
"""
|
||||||
if paneNo == 1:
|
if paneNo == 1:
|
||||||
self.treeView.setFocus()
|
self.treeView.setFocus()
|
||||||
elif paneNo == 2:
|
elif paneNo == 2:
|
||||||
@@ -926,6 +929,8 @@ class GuiMain(QMainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def closeDocEditor(self):
|
def closeDocEditor(self):
|
||||||
|
"""Close the document edit panel. This does not hide the editor.
|
||||||
|
"""
|
||||||
self.closeDocument()
|
self.closeDocument()
|
||||||
self.theProject.setLastEdited(None)
|
self.theProject.setLastEdited(None)
|
||||||
return
|
return
|
||||||
@@ -1059,6 +1064,8 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _setWindowTitle(self, projName=None):
|
def _setWindowTitle(self, projName=None):
|
||||||
|
"""Set the window title and add the project's working title.
|
||||||
|
"""
|
||||||
winTitle = self.mainConf.appName
|
winTitle = self.mainConf.appName
|
||||||
if projName is not None:
|
if projName is not None:
|
||||||
winTitle += " - %s" % projName
|
winTitle += " - %s" % projName
|
||||||
@@ -1066,19 +1073,30 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _autoSaveProject(self):
|
def _autoSaveProject(self):
|
||||||
if (self.hasProject and self.theProject.projChanged and
|
"""Triggered by the auto-save project timer to save the project.
|
||||||
self.theProject.projPath is not None):
|
"""
|
||||||
|
doSave = self.hasProject
|
||||||
|
doSave &= self.theProject.projChanged
|
||||||
|
doSave &= self.theProject.projPath is not None
|
||||||
|
|
||||||
|
if doSave:
|
||||||
logger.debug("Autosaving project")
|
logger.debug("Autosaving project")
|
||||||
self.saveProject(autoSave=True)
|
self.saveProject(autoSave=True)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _autoSaveDocument(self):
|
def _autoSaveDocument(self):
|
||||||
|
"""Triggered by the auto-save document timer to save the
|
||||||
|
document.
|
||||||
|
"""
|
||||||
if self.hasProject and self.docEditor.docChanged:
|
if self.hasProject and self.docEditor.docChanged:
|
||||||
logger.debug("Autosaving document")
|
logger.debug("Autosaving document")
|
||||||
self.saveDocument()
|
self.saveDocument()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _makeStatusIcons(self):
|
def _makeStatusIcons(self):
|
||||||
|
"""Generate all the item status icons based on project settings.
|
||||||
|
"""
|
||||||
self.statusIcons = {}
|
self.statusIcons = {}
|
||||||
iPx = self.mainConf.pxInt(32)
|
iPx = self.mainConf.pxInt(32)
|
||||||
for sLabel, sCol, _ in self.theProject.statusItems:
|
for sLabel, sCol, _ in self.theProject.statusItems:
|
||||||
@@ -1088,6 +1106,9 @@ class GuiMain(QMainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _makeImportIcons(self):
|
def _makeImportIcons(self):
|
||||||
|
"""Generate all the item importance icons based on project
|
||||||
|
settings.
|
||||||
|
"""
|
||||||
self.importIcons = {}
|
self.importIcons = {}
|
||||||
iPx = self.mainConf.pxInt(32)
|
iPx = self.mainConf.pxInt(32)
|
||||||
for sLabel, sCol, _ in self.theProject.importItems:
|
for sLabel, sCol, _ in self.theProject.importItems:
|
||||||
@@ -1101,6 +1122,9 @@ class GuiMain(QMainWindow):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def closeEvent(self, theEvent):
|
def closeEvent(self, theEvent):
|
||||||
|
"""Capture the closing event of the GUI and call the close
|
||||||
|
function to handle all the close process steps.
|
||||||
|
"""
|
||||||
if self.closeMain():
|
if self.closeMain():
|
||||||
theEvent.accept()
|
theEvent.accept()
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user