Change assetPath to a Path object
This commit is contained in:
@@ -27,7 +27,6 @@ import sys
|
|||||||
import getopt
|
import getopt
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt5.QtGui import QIcon
|
|
||||||
from PyQt5.QtWidgets import QApplication, QErrorMessage
|
from PyQt5.QtWidgets import QApplication, QErrorMessage
|
||||||
|
|
||||||
from novelwriter.error import exceptionHandler, logException
|
from novelwriter.error import exceptionHandler, logException
|
||||||
@@ -249,7 +248,6 @@ def main(sysArgs=None):
|
|||||||
nwApp = QApplication([CONFIG.appName, (f"-style={qtStyle}")])
|
nwApp = QApplication([CONFIG.appName, (f"-style={qtStyle}")])
|
||||||
nwApp.setApplicationName(CONFIG.appName)
|
nwApp.setApplicationName(CONFIG.appName)
|
||||||
nwApp.setApplicationVersion(__version__)
|
nwApp.setApplicationVersion(__version__)
|
||||||
nwApp.setWindowIcon(QIcon(CONFIG.appIcon))
|
|
||||||
nwApp.setOrganizationDomain(__domain__)
|
nwApp.setOrganizationDomain(__domain__)
|
||||||
|
|
||||||
# Connect the exception handler before making the main GUI
|
# Connect the exception handler before making the main GUI
|
||||||
|
|||||||
+63
-57
@@ -51,6 +51,9 @@ class Config:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
|
# Initialisation
|
||||||
|
# ==============
|
||||||
|
|
||||||
# Set Application Variables
|
# Set Application Variables
|
||||||
self.appName = "novelWriter"
|
self.appName = "novelWriter"
|
||||||
self.appHandle = "novelwriter"
|
self.appHandle = "novelwriter"
|
||||||
@@ -62,20 +65,37 @@ class Config:
|
|||||||
self._confPath = confRoot.absolute() / self.appHandle # The user config location
|
self._confPath = confRoot.absolute() / self.appHandle # The user config location
|
||||||
self._dataPath = dataRoot.absolute() / self.appHandle # The user data location
|
self._dataPath = dataRoot.absolute() / self.appHandle # The user data location
|
||||||
|
|
||||||
self.cmdOpen = None # Path from command line for project to be opened on launch
|
if hasattr(sys, "_MEIPASS"):
|
||||||
self.lastPath = None # The last user-selected folder (browse dialogs)
|
self._appPath = Path(sys._MEIPASS).absolute()
|
||||||
self.appPath = None # The full path to the novelwriter package folder
|
else:
|
||||||
self.appRoot = None # The full path to the novelwriter root folder
|
self._appPath = Path(__file__).parent.absolute()
|
||||||
self.appIcon = None # The full path to the novelwriter icon file
|
|
||||||
self.assetPath = None # The full path to the novelwriter/assets folder
|
self._appRoot = self._appPath.parent
|
||||||
self.pdfDocs = None # The location of the PDF manual, if it exists
|
if self._appRoot.is_file():
|
||||||
|
# novelWriter is packaged as a single file
|
||||||
|
self._appRoot = self._appRoot.parent
|
||||||
|
self._appPath = self._appRoot
|
||||||
|
|
||||||
|
self.cmdOpen = None # Path from command line for project to be opened on launch
|
||||||
|
self.lastPath = None # The last user-selected folder (browse dialogs)
|
||||||
|
self.pdfDocs = None # The location of the PDF manual, if it exists
|
||||||
|
|
||||||
# Runtime Settings and Variables
|
# Runtime Settings and Variables
|
||||||
self.hasError = False # True if the config class encountered an error
|
self.hasError = False # True if the config class encountered an error
|
||||||
self.errData = [] # List of error messages
|
self.errData = [] # List of error messages
|
||||||
self.confChanged = False # True whenever the config has chenged, false after save
|
self.confChanged = False # True whenever the config has chenged, false after save
|
||||||
|
|
||||||
# General
|
# Localisation Info
|
||||||
|
self._qLocal = QLocale.system()
|
||||||
|
self._qtTrans = {}
|
||||||
|
self._qtLangPath = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
|
||||||
|
self._nwLangPath = str(self._appPath / "assets" / "i18n")
|
||||||
|
|
||||||
|
# User Settings
|
||||||
|
# =============
|
||||||
|
|
||||||
|
# General GUI Settings
|
||||||
|
self.guiLang = self._qLocal.name()
|
||||||
self.guiTheme = "" # GUI theme
|
self.guiTheme = "" # GUI theme
|
||||||
self.guiSyntax = "" # Syntax theme
|
self.guiSyntax = "" # Syntax theme
|
||||||
self.guiFont = "" # Defaults to system default font
|
self.guiFont = "" # Defaults to system default font
|
||||||
@@ -86,14 +106,7 @@ class Config:
|
|||||||
self.setDefaultGuiTheme()
|
self.setDefaultGuiTheme()
|
||||||
self.setDefaultSyntaxTheme()
|
self.setDefaultSyntaxTheme()
|
||||||
|
|
||||||
# Localisation
|
# Size Settings
|
||||||
self.qLocal = QLocale.system()
|
|
||||||
self.guiLang = self.qLocal.name()
|
|
||||||
self.qtLangPath = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
|
|
||||||
self.nwLangPath = None
|
|
||||||
self.qtTrans = {}
|
|
||||||
|
|
||||||
# Sizes
|
|
||||||
self.winGeometry = [1200, 650]
|
self.winGeometry = [1200, 650]
|
||||||
self.prefGeometry = [700, 615]
|
self.prefGeometry = [700, 615]
|
||||||
self.projColWidth = [200, 60, 140]
|
self.projColWidth = [200, 60, 140]
|
||||||
@@ -103,16 +116,16 @@ class Config:
|
|||||||
self.outlnPanePos = [500, 150]
|
self.outlnPanePos = [500, 150]
|
||||||
self.isFullScreen = False
|
self.isFullScreen = False
|
||||||
|
|
||||||
# Features
|
# Feature Settings
|
||||||
self.hideVScroll = False # Hide vertical scroll bars on main widgets
|
self.hideVScroll = False # Hide vertical scroll bars on main widgets
|
||||||
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
|
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
|
||||||
self.emphLabels = True # Add emphasis to H1 and H2 item labels
|
self.emphLabels = True # Add emphasis to H1 and H2 item labels
|
||||||
|
|
||||||
# Project
|
# Project Settings
|
||||||
self.autoSaveProj = 60 # Interval for auto-saving project in seconds
|
self.autoSaveProj = 60 # Interval for auto-saving project in seconds
|
||||||
self.autoSaveDoc = 30 # Interval for auto-saving document in seconds
|
self.autoSaveDoc = 30 # Interval for auto-saving document in seconds
|
||||||
|
|
||||||
# Text Editor
|
# Text Editor Settings
|
||||||
self.textFont = None # Editor font
|
self.textFont = None # Editor font
|
||||||
self.textSize = 12 # Editor font size
|
self.textSize = 12 # Editor font size
|
||||||
self.textWidth = 700 # Editor text width
|
self.textWidth = 700 # Editor text width
|
||||||
@@ -151,7 +164,7 @@ class Config:
|
|||||||
self.stopWhenIdle = True # Stop the status bar clock when the user is idle
|
self.stopWhenIdle = True # Stop the status bar clock when the user is idle
|
||||||
self.userIdleTime = 300 # Time of inactivity to consider user idle
|
self.userIdleTime = 300 # Time of inactivity to consider user idle
|
||||||
|
|
||||||
# User-Selected Symbols
|
# User-Selected Symbol Settings
|
||||||
self.fmtApostrophe = nwUnicode.U_RSQUO
|
self.fmtApostrophe = nwUnicode.U_RSQUO
|
||||||
self.fmtSingleQuotes = [nwUnicode.U_LSQUO, nwUnicode.U_RSQUO]
|
self.fmtSingleQuotes = [nwUnicode.U_LSQUO, nwUnicode.U_RSQUO]
|
||||||
self.fmtDoubleQuotes = [nwUnicode.U_LDQUO, nwUnicode.U_RDQUO]
|
self.fmtDoubleQuotes = [nwUnicode.U_LDQUO, nwUnicode.U_RDQUO]
|
||||||
@@ -159,7 +172,7 @@ class Config:
|
|||||||
self.fmtPadAfter = ""
|
self.fmtPadAfter = ""
|
||||||
self.fmtPadThin = False
|
self.fmtPadThin = False
|
||||||
|
|
||||||
# Spell Checking
|
# Spell Checking Settings
|
||||||
self.spellLanguage = None
|
self.spellLanguage = None
|
||||||
|
|
||||||
# Search Bar Switches
|
# Search Bar Switches
|
||||||
@@ -170,7 +183,7 @@ class Config:
|
|||||||
self.searchNextFile = False
|
self.searchNextFile = False
|
||||||
self.searchMatchCap = False
|
self.searchMatchCap = False
|
||||||
|
|
||||||
# Backup
|
# Backup Settings
|
||||||
self.backupPath = ""
|
self.backupPath = ""
|
||||||
self.backupOnClose = False
|
self.backupOnClose = False
|
||||||
self.askBeforeBackup = True
|
self.askBeforeBackup = True
|
||||||
@@ -180,6 +193,9 @@ class Config:
|
|||||||
self.viewComments = True # Comments are shown in the viewer
|
self.viewComments = True # Comments are shown in the viewer
|
||||||
self.viewSynopsis = True # Synopsis is shown in the viewer
|
self.viewSynopsis = True # Synopsis is shown in the viewer
|
||||||
|
|
||||||
|
# System and App Information
|
||||||
|
# ==========================
|
||||||
|
|
||||||
# Check Qt5 Versions
|
# Check Qt5 Versions
|
||||||
verQt = splitVersionNumber(QT_VERSION_STR)
|
verQt = splitVersionNumber(QT_VERSION_STR)
|
||||||
self.verQtString = QT_VERSION_STR
|
self.verQtString = QT_VERSION_STR
|
||||||
@@ -254,6 +270,13 @@ class Config:
|
|||||||
return self._dataPath / target
|
return self._dataPath / target
|
||||||
return self._dataPath
|
return self._dataPath
|
||||||
|
|
||||||
|
def getAssetPath(self, target=None):
|
||||||
|
"""Return a path in the assets folder.
|
||||||
|
"""
|
||||||
|
if isinstance(target, str):
|
||||||
|
return self._appPath / "assets" / target
|
||||||
|
return self._appPath / "assets"
|
||||||
|
|
||||||
##
|
##
|
||||||
# Config Actions
|
# Config Actions
|
||||||
##
|
##
|
||||||
@@ -271,29 +294,12 @@ class Config:
|
|||||||
logger.info("Setting data path from alternative path: %s", dataPath)
|
logger.info("Setting data path from alternative path: %s", dataPath)
|
||||||
self._dataPath = Path(dataPath)
|
self._dataPath = Path(dataPath)
|
||||||
|
|
||||||
logger.debug("Config path: %s", self._confPath)
|
logger.debug("Config Path: %s", self._confPath)
|
||||||
logger.debug("Data path: %s", self._dataPath)
|
logger.debug("Data Path: %s", self._dataPath)
|
||||||
|
logger.debug("App Root: %s", self._appRoot)
|
||||||
|
logger.debug("App Path: %s", self._appPath)
|
||||||
|
|
||||||
self.lastPath = os.path.expanduser("~")
|
self.lastPath = os.path.expanduser("~")
|
||||||
self.appPath = getattr(sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__)))
|
|
||||||
self.appRoot = os.path.abspath(os.path.join(self.appPath, os.path.pardir))
|
|
||||||
|
|
||||||
if os.path.isfile(self.appRoot):
|
|
||||||
# novelWriter is packaged as a single file, so the app and
|
|
||||||
# root paths are the same, and equal to the folder that
|
|
||||||
# contains the single executable.
|
|
||||||
self.appRoot = os.path.dirname(self.appRoot)
|
|
||||||
self.appPath = self.appRoot
|
|
||||||
|
|
||||||
# Assets
|
|
||||||
self.assetPath = os.path.join(self.appPath, "assets")
|
|
||||||
self.appIcon = os.path.join(self.assetPath, "icons", "novelwriter.svg")
|
|
||||||
|
|
||||||
# Internationalisation
|
|
||||||
self.nwLangPath = os.path.join(self.assetPath, "i18n")
|
|
||||||
|
|
||||||
logger.debug("Assets: %s", self.assetPath)
|
|
||||||
logger.debug("App path: %s", self.appPath)
|
|
||||||
logger.debug("Last path: %s", self.lastPath)
|
logger.debug("Last path: %s", self.lastPath)
|
||||||
|
|
||||||
# If the config and data folders don't not exist, create them
|
# If the config and data folders don't not exist, create them
|
||||||
@@ -324,9 +330,9 @@ class Config:
|
|||||||
self.spellLanguage = "en"
|
self.spellLanguage = "en"
|
||||||
|
|
||||||
# Look for a PDF version of the manual
|
# Look for a PDF version of the manual
|
||||||
pdfDocs = os.path.join(self.assetPath, "manual.pdf")
|
pdfDocs = self._appPath / "assets" / "manual.pdf"
|
||||||
if os.path.isfile(pdfDocs):
|
if pdfDocs.is_file():
|
||||||
logger.debug("Found manual: %s", pdfDocs)
|
logger.debug("Found PDF manual: %s", pdfDocs)
|
||||||
self.pdfDocs = pdfDocs
|
self.pdfDocs = pdfDocs
|
||||||
|
|
||||||
logger.debug("Config initialisation complete")
|
logger.debug("Config initialisation complete")
|
||||||
@@ -336,24 +342,24 @@ class Config:
|
|||||||
def initLocalisation(self, nwApp):
|
def initLocalisation(self, nwApp):
|
||||||
"""Initialise the localisation of the GUI.
|
"""Initialise the localisation of the GUI.
|
||||||
"""
|
"""
|
||||||
self.qLocal = QLocale(self.guiLang)
|
self._qLocal = QLocale(self.guiLang)
|
||||||
QLocale.setDefault(self.qLocal)
|
QLocale.setDefault(self._qLocal)
|
||||||
self.qtTrans = {}
|
self._qtTrans = {}
|
||||||
|
|
||||||
langList = [
|
langList = [
|
||||||
(self.qtLangPath, "qtbase"), # Qt 5.x
|
(self._qtLangPath, "qtbase"), # Qt 5.x
|
||||||
(self.nwLangPath, "qtbase"), # Alternative Qt 5.x
|
(self._nwLangPath, "qtbase"), # Alternative Qt 5.x
|
||||||
(self.nwLangPath, "nw"), # novelWriter
|
(self._nwLangPath, "nw"), # novelWriter
|
||||||
]
|
]
|
||||||
for lngPath, lngBase in langList:
|
for lngPath, lngBase in langList:
|
||||||
for lngCode in self.qLocal.uiLanguages():
|
for lngCode in self._qLocal.uiLanguages():
|
||||||
qTrans = QTranslator()
|
qTrans = QTranslator()
|
||||||
lngFile = "%s_%s" % (lngBase, lngCode.replace("-", "_"))
|
lngFile = "%s_%s" % (lngBase, lngCode.replace("-", "_"))
|
||||||
if lngFile not in self.qtTrans:
|
if lngFile not in self._qtTrans:
|
||||||
if qTrans.load(lngFile, lngPath):
|
if qTrans.load(lngFile, lngPath):
|
||||||
logger.debug("Loaded: %s", os.path.join(lngPath, lngFile))
|
logger.debug("Loaded: %s", os.path.join(lngPath, lngFile))
|
||||||
nwApp.installTranslator(qTrans)
|
nwApp.installTranslator(qTrans)
|
||||||
self.qtTrans[lngFile] = qTrans
|
self._qtTrans[lngFile] = qTrans
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -372,8 +378,8 @@ class Config:
|
|||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
for qmFile in os.listdir(self.nwLangPath):
|
for qmFile in os.listdir(self._nwLangPath):
|
||||||
if not os.path.isfile(os.path.join(self.nwLangPath, qmFile)):
|
if not os.path.isfile(os.path.join(self._nwLangPath, qmFile)):
|
||||||
continue
|
continue
|
||||||
if not qmFile.startswith(fPre) or not qmFile.endswith(fExt):
|
if not qmFile.startswith(fPre) or not qmFile.endswith(fExt):
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
import shutil
|
||||||
import logging
|
import logging
|
||||||
import novelwriter
|
import novelwriter
|
||||||
@@ -431,8 +430,8 @@ class ProjectBuilder:
|
|||||||
logger.error("No project path set for the example project")
|
logger.error("No project path set for the example project")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
pkgSample = os.path.join(self.mainConf.assetPath, "sample.zip")
|
pkgSample = self.mainConf.getAssetPath("sample.zip")
|
||||||
if os.path.isfile(pkgSample):
|
if pkgSample.is_file():
|
||||||
try:
|
try:
|
||||||
shutil.unpack_archive(pkgSample, projPath)
|
shutil.unpack_archive(pkgSample, projPath)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
@@ -698,13 +698,13 @@ class NWProject(QObject):
|
|||||||
def _loadProjectLocalisation(self):
|
def _loadProjectLocalisation(self):
|
||||||
"""Load the language data for the current project language.
|
"""Load the language data for the current project language.
|
||||||
"""
|
"""
|
||||||
if self._data.language is None or self.mainConf.nwLangPath is None:
|
if self._data.language is None or self.mainConf._nwLangPath is None:
|
||||||
self._langData = {}
|
self._langData = {}
|
||||||
return False
|
return False
|
||||||
|
|
||||||
langFile = Path(self.mainConf.nwLangPath) / f"project_{self._data.language}.json"
|
langFile = Path(self.mainConf._nwLangPath) / f"project_{self._data.language}.json"
|
||||||
if not langFile.is_file():
|
if not langFile.is_file():
|
||||||
langFile = Path(self.mainConf.nwLangPath) / "project_en_GB.json"
|
langFile = Path(self.mainConf._nwLangPath) / "project_en_GB.json"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(langFile, mode="r", encoding="utf-8") as inFile:
|
with open(langFile, mode="r", encoding="utf-8") as inFile:
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
import novelwriter
|
import novelwriter
|
||||||
|
|
||||||
@@ -233,7 +232,7 @@ class GuiAbout(QDialog):
|
|||||||
def _fillNotesPage(self):
|
def _fillNotesPage(self):
|
||||||
"""Load the content for the Release Notes page.
|
"""Load the content for the Release Notes page.
|
||||||
"""
|
"""
|
||||||
docPath = os.path.join(self.mainConf.assetPath, "text", "release_notes.htm")
|
docPath = self.mainConf.getAssetPath("text") / "release_notes.htm"
|
||||||
docText = readTextFile(docPath)
|
docText = readTextFile(docPath)
|
||||||
if docText:
|
if docText:
|
||||||
self.pageNotes.setHtml(docText)
|
self.pageNotes.setHtml(docText)
|
||||||
@@ -244,7 +243,7 @@ class GuiAbout(QDialog):
|
|||||||
def _fillLicensePage(self):
|
def _fillLicensePage(self):
|
||||||
"""Load the content for the Licence page.
|
"""Load the content for the Licence page.
|
||||||
"""
|
"""
|
||||||
docPath = os.path.join(self.mainConf.assetPath, "text", "gplv3_en.htm")
|
docPath = self.mainConf.getAssetPath("text") / "gplv3_en.htm"
|
||||||
docText = readTextFile(docPath)
|
docText = readTextFile(docPath)
|
||||||
if docText:
|
if docText:
|
||||||
self.pageLicense.setHtml(docText)
|
self.pageLicense.setHtml(docText)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
import logging
|
import logging
|
||||||
import novelwriter
|
import novelwriter
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
from urllib.request import pathname2url
|
from urllib.request import pathname2url
|
||||||
|
|
||||||
@@ -104,10 +105,11 @@ class GuiMainMenu(QMenuBar):
|
|||||||
def _openUserManualFile(self):
|
def _openUserManualFile(self):
|
||||||
"""Open the documentation in PDF format.
|
"""Open the documentation in PDF format.
|
||||||
"""
|
"""
|
||||||
if self.mainConf.pdfDocs is None:
|
if isinstance(self.mainConf.pdfDocs, Path):
|
||||||
return False
|
QDesktopServices.openUrl(
|
||||||
QDesktopServices.openUrl(QUrl(urljoin("file:", pathname2url(self.mainConf.pdfDocs))))
|
QUrl(urljoin("file:", pathname2url(str(self.mainConf.pdfDocs))))
|
||||||
return True
|
)
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Menu Builders
|
# Menu Builders
|
||||||
@@ -881,7 +883,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.helpMenu.addAction(self.aHelpDocs)
|
self.helpMenu.addAction(self.aHelpDocs)
|
||||||
|
|
||||||
# Help > User Manual (PDF)
|
# Help > User Manual (PDF)
|
||||||
if self.mainConf.pdfDocs is not None:
|
if isinstance(self.mainConf.pdfDocs, Path):
|
||||||
self.aPdfDocs = QAction(self.tr("User Manual (PDF)"), self)
|
self.aPdfDocs = QAction(self.tr("User Manual (PDF)"), self)
|
||||||
self.aPdfDocs.setShortcut("Shift+F1")
|
self.aPdfDocs.setShortcut("Shift+F1")
|
||||||
self.aPdfDocs.triggered.connect(self._openUserManualFile)
|
self.aPdfDocs.triggered.connect(self._openUserManualFile)
|
||||||
|
|||||||
+15
-22
@@ -24,12 +24,10 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
import novelwriter
|
import novelwriter
|
||||||
|
|
||||||
from math import ceil
|
from math import ceil
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import qApp
|
from PyQt5.QtWidgets import qApp
|
||||||
@@ -120,9 +118,8 @@ class GuiTheme:
|
|||||||
self._availThemes = {}
|
self._availThemes = {}
|
||||||
self._availSyntax = {}
|
self._availSyntax = {}
|
||||||
|
|
||||||
self._listConf(self._availSyntax, os.path.join(self.mainConf.assetPath, "syntax"))
|
self._listConf(self._availSyntax, self.mainConf.getAssetPath("syntax"))
|
||||||
self._listConf(self._availThemes, os.path.join(self.mainConf.assetPath, "themes"))
|
self._listConf(self._availThemes, self.mainConf.getAssetPath("themes"))
|
||||||
|
|
||||||
self._listConf(self._availSyntax, self.mainConf.getDataPath("syntax"))
|
self._listConf(self._availSyntax, self.mainConf.getDataPath("syntax"))
|
||||||
self._listConf(self._availThemes, self.mainConf.getDataPath("themes"))
|
self._listConf(self._availThemes, self.mainConf.getDataPath("themes"))
|
||||||
|
|
||||||
@@ -380,7 +377,6 @@ class GuiTheme:
|
|||||||
def _listConf(self, targetDict, checkDir):
|
def _listConf(self, targetDict, checkDir):
|
||||||
"""Scan for theme config files and populate the dictionary.
|
"""Scan for theme config files and populate the dictionary.
|
||||||
"""
|
"""
|
||||||
checkDir = Path(checkDir)
|
|
||||||
if not checkDir.is_dir():
|
if not checkDir.is_dir():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -476,7 +472,7 @@ class GuiIcons:
|
|||||||
self._confName = "icons.conf"
|
self._confName = "icons.conf"
|
||||||
|
|
||||||
# Icon Theme Path
|
# Icon Theme Path
|
||||||
self._iconPath = os.path.join(self.mainConf.assetPath, "icons")
|
self._iconPath = self.mainConf.getAssetPath("icons")
|
||||||
|
|
||||||
# Icon Theme Meta
|
# Icon Theme Meta
|
||||||
self.themeName = ""
|
self.themeName = ""
|
||||||
@@ -499,12 +495,12 @@ class GuiIcons:
|
|||||||
update functions for the classes where they're used.
|
update functions for the classes where they're used.
|
||||||
"""
|
"""
|
||||||
self._themeMap = {}
|
self._themeMap = {}
|
||||||
themePath = os.path.join(self.mainConf.assetPath, "icons", iconTheme)
|
themePath = self._iconPath / iconTheme
|
||||||
if not os.path.isdir(themePath):
|
if not themePath.is_dir():
|
||||||
logger.warning("No icons loaded for '%s'", iconTheme)
|
logger.warning("No icons loaded for '%s'", iconTheme)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
themeConf = os.path.join(themePath, self._confName)
|
themeConf = themePath / self._confName
|
||||||
logger.info("Loading icon theme '%s'", iconTheme)
|
logger.info("Loading icon theme '%s'", iconTheme)
|
||||||
|
|
||||||
# Config File
|
# Config File
|
||||||
@@ -535,8 +531,8 @@ class GuiIcons:
|
|||||||
if iconName not in self.ICON_KEYS:
|
if iconName not in self.ICON_KEYS:
|
||||||
logger.error("Unknown icon name '%s' in config file", iconName)
|
logger.error("Unknown icon name '%s' in config file", iconName)
|
||||||
else:
|
else:
|
||||||
iconPath = os.path.join(themePath, iconFile)
|
iconPath = themePath / iconFile
|
||||||
if os.path.isfile(iconPath):
|
if iconPath.is_file():
|
||||||
self._themeMap[iconName] = iconPath
|
self._themeMap[iconName] = iconPath
|
||||||
logger.debug("Icon slot '%s' using file '%s'", iconName, iconFile)
|
logger.debug("Icon slot '%s' using file '%s'", iconName, iconFile)
|
||||||
else:
|
else:
|
||||||
@@ -572,18 +568,16 @@ class GuiIcons:
|
|||||||
if decoKey in self._themeMap:
|
if decoKey in self._themeMap:
|
||||||
imgPath = self._themeMap[decoKey]
|
imgPath = self._themeMap[decoKey]
|
||||||
elif decoKey in self.IMAGE_MAP:
|
elif decoKey in self.IMAGE_MAP:
|
||||||
imgPath = os.path.join(
|
imgPath = self.mainConf.getAssetPath("images") / self.IMAGE_MAP[decoKey]
|
||||||
self.mainConf.assetPath, "images", self.IMAGE_MAP[decoKey]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
logger.error("Decoration with name '%s' does not exist", decoKey)
|
logger.error("Decoration with name '%s' does not exist", decoKey)
|
||||||
return QPixmap()
|
return QPixmap()
|
||||||
|
|
||||||
if not os.path.isfile(imgPath):
|
if not imgPath.is_file():
|
||||||
logger.error("Asset not found: %s", imgPath)
|
logger.error("Asset not found: %s", imgPath)
|
||||||
return QPixmap()
|
return QPixmap()
|
||||||
|
|
||||||
theDeco = QPixmap(imgPath)
|
theDeco = QPixmap(str(imgPath))
|
||||||
if pxW is not None and pxH is not None:
|
if pxW is not None and pxH is not None:
|
||||||
return theDeco.scaled(pxW, pxH, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
|
return theDeco.scaled(pxW, pxH, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
|
||||||
elif pxW is None and pxH is not None:
|
elif pxW is None and pxH is not None:
|
||||||
@@ -667,15 +661,14 @@ class GuiIcons:
|
|||||||
|
|
||||||
# If we just want the app icons, return right away
|
# If we just want the app icons, return right away
|
||||||
if iconKey == "novelwriter":
|
if iconKey == "novelwriter":
|
||||||
return QIcon(os.path.join(self._iconPath, "novelwriter.svg"))
|
return QIcon(str(self._iconPath / "novelwriter.svg"))
|
||||||
elif iconKey == "proj_nwx":
|
elif iconKey == "proj_nwx":
|
||||||
return QIcon(os.path.join(self._iconPath, "x-novelwriter-project.svg"))
|
return QIcon(str(self._iconPath / "x-novelwriter-project.svg"))
|
||||||
|
|
||||||
# Otherwise, we load from the theme folder
|
# Otherwise, we load from the theme folder
|
||||||
if iconKey in self._themeMap:
|
if iconKey in self._themeMap:
|
||||||
relPath = os.path.relpath(self._themeMap[iconKey], self._iconPath)
|
logger.debug("Loading: %s", self._themeMap[iconKey].name)
|
||||||
logger.debug("Loading: %s", relPath)
|
return QIcon(str(self._themeMap[iconKey]))
|
||||||
return QIcon(self._themeMap[iconKey])
|
|
||||||
|
|
||||||
# If we didn't find one, give up and return an empty icon
|
# If we didn't find one, give up and return an empty icon
|
||||||
logger.warning("Did not load an icon for '%s'", iconKey)
|
logger.warning("Did not load an icon for '%s'", iconKey)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import novelwriter
|
|||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from time import time
|
from time import time
|
||||||
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
|
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
|
||||||
@@ -95,7 +96,11 @@ class GuiMain(QMainWindow):
|
|||||||
# Prepare Main Window
|
# Prepare Main Window
|
||||||
self.resize(*self.mainConf.getWinSize())
|
self.resize(*self.mainConf.getWinSize())
|
||||||
self._updateWindowTitle()
|
self._updateWindowTitle()
|
||||||
self.setWindowIcon(QIcon(self.mainConf.appIcon))
|
|
||||||
|
nwIcon = self.mainConf.getAssetPath("icons") / "novelwriter.svg"
|
||||||
|
self.nwIcon = QIcon(str(nwIcon)) if nwIcon.is_file() else QIcon()
|
||||||
|
self.setWindowIcon(self.nwIcon)
|
||||||
|
qApp.setWindowIcon(self.nwIcon)
|
||||||
|
|
||||||
# Build the GUI
|
# Build the GUI
|
||||||
# =============
|
# =============
|
||||||
@@ -1362,7 +1367,7 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
# Help
|
# Help
|
||||||
self.addAction(self.mainMenu.aHelpDocs)
|
self.addAction(self.mainMenu.aHelpDocs)
|
||||||
if self.mainConf.pdfDocs is not None:
|
if isinstance(self.mainConf.pdfDocs, Path):
|
||||||
self.addAction(self.mainMenu.aPdfDocs)
|
self.addAction(self.mainMenu.aPdfDocs)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
import novelwriter
|
import novelwriter
|
||||||
@@ -120,7 +119,7 @@ class GuiLipsum(QDialog):
|
|||||||
def _doInsert(self):
|
def _doInsert(self):
|
||||||
"""Load the text and insert it in the open document.
|
"""Load the text and insert it in the open document.
|
||||||
"""
|
"""
|
||||||
lipsumFile = os.path.join(self.mainConf.assetPath, "text", "lipsum.txt")
|
lipsumFile = self.mainConf.getAssetPath("text") / "lipsum.txt"
|
||||||
lipsumText = readTextFile(lipsumFile).splitlines()
|
lipsumText = readTextFile(lipsumFile).splitlines()
|
||||||
|
|
||||||
if self.randSwitch.isChecked():
|
if self.randSwitch.isChecked():
|
||||||
|
|||||||
@@ -159,14 +159,14 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
|
|||||||
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
|
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
|
||||||
assert tstConf._confPath == tmpDir
|
assert tstConf._confPath == tmpDir
|
||||||
assert tstConf._dataPath == tmpDir
|
assert tstConf._dataPath == tmpDir
|
||||||
appRoot = tstConf.appRoot
|
appRoot = tstConf._appRoot
|
||||||
|
|
||||||
mp.setattr("os.path.isfile", lambda *a: True)
|
mp.setattr("os.path.isfile", lambda *a: True)
|
||||||
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
|
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
|
||||||
assert tstConf._confPath == tmpDir
|
assert tstConf._confPath == tmpDir
|
||||||
assert tstConf._dataPath == tmpDir
|
assert tstConf._dataPath == tmpDir
|
||||||
assert tstConf.appRoot == os.path.dirname(appRoot)
|
assert tstConf._appRoot == os.path.dirname(appRoot)
|
||||||
assert tstConf.appPath == os.path.dirname(appRoot)
|
assert tstConf._appPath == os.path.dirname(appRoot)
|
||||||
|
|
||||||
assert tstConf.loadConfig() is True
|
assert tstConf.loadConfig() is True
|
||||||
assert tstConf.saveConfig() is True
|
assert tstConf.saveConfig() is True
|
||||||
@@ -199,7 +199,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
|
|||||||
i18nDir = os.path.join(fncDir, "i18n")
|
i18nDir = os.path.join(fncDir, "i18n")
|
||||||
os.mkdir(i18nDir)
|
os.mkdir(i18nDir)
|
||||||
os.mkdir(os.path.join(i18nDir, "stuff"))
|
os.mkdir(os.path.join(i18nDir, "stuff"))
|
||||||
tstConf.nwLangPath = i18nDir
|
tstConf._nwLangPath = i18nDir
|
||||||
|
|
||||||
copyfile(os.path.join(filesDir, "nw_en_GB.qm"), os.path.join(i18nDir, "nw_en_GB.qm"))
|
copyfile(os.path.join(filesDir, "nw_en_GB.qm"), os.path.join(i18nDir, "nw_en_GB.qm"))
|
||||||
writeFile(os.path.join(i18nDir, "nw_en_GB.ts"), "")
|
writeFile(os.path.join(i18nDir, "nw_en_GB.ts"), "")
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ def testCoreTools_NewCustomB(monkeypatch, fncDir, outDir, refDir, mockGUI, mockR
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreTools_NewSample(fncDir, tmpConf, mockGUI, tmpDir):
|
def testCoreTools_NewSample(monkeypatch, fncPath, tmpConf, tmpPath, mockGUI):
|
||||||
"""Check that we can create a new project can be created from the
|
"""Check that we can create a new project can be created from the
|
||||||
provided sample project via a zip file.
|
provided sample project via a zip file.
|
||||||
"""
|
"""
|
||||||
@@ -380,7 +380,7 @@ def testCoreTools_NewSample(fncDir, tmpConf, mockGUI, tmpDir):
|
|||||||
"projName": "Test Sample",
|
"projName": "Test Sample",
|
||||||
"projTitle": "Test Novel",
|
"projTitle": "Test Novel",
|
||||||
"projAuthors": "Jane Doe\nJohn Doh\n",
|
"projAuthors": "Jane Doe\nJohn Doh\n",
|
||||||
"projPath": fncDir,
|
"projPath": fncPath,
|
||||||
"popSample": True,
|
"popSample": True,
|
||||||
"popMinimal": False,
|
"popMinimal": False,
|
||||||
"popCustom": False,
|
"popCustom": False,
|
||||||
@@ -392,9 +392,11 @@ def testCoreTools_NewSample(fncDir, tmpConf, mockGUI, tmpDir):
|
|||||||
assert projBuild.buildProject({"popSample": True}) is False
|
assert projBuild.buildProject({"popSample": True}) is False
|
||||||
|
|
||||||
# Force the lookup path for assets to our temp folder
|
# Force the lookup path for assets to our temp folder
|
||||||
srcSample = os.path.abspath(os.path.join(tmpConf.appRoot, "sample"))
|
srcSample = tmpConf._appRoot / "sample"
|
||||||
dstSample = os.path.join(tmpDir, "sample.zip")
|
dstSample = tmpPath / "sample.zip"
|
||||||
tmpConf.assetPath = tmpDir
|
monkeypatch.setattr(
|
||||||
|
"novelwriter.config.Config.getAssetPath", lambda *a: tmpPath / "sample.zip"
|
||||||
|
)
|
||||||
|
|
||||||
# Cannot extract when the zip does not exist
|
# Cannot extract when the zip does not exist
|
||||||
assert projBuild.buildProject(projData) is False
|
assert projBuild.buildProject(projData) is False
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from tools import getGuiItem
|
from tools import getGuiItem
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QAction, QMessageBox
|
from PyQt5.QtWidgets import QAction, QMessageBox
|
||||||
@@ -29,7 +31,7 @@ from novelwriter.dialogs.about import GuiAbout
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testDlgAbout_NWDialog(qtbot, nwGUI):
|
def testDlgAbout_NWDialog(qtbot, monkeypatch, nwGUI):
|
||||||
"""Test the novelWriter about dialogs.
|
"""Test the novelWriter about dialogs.
|
||||||
"""
|
"""
|
||||||
# NW About
|
# NW About
|
||||||
@@ -45,13 +47,12 @@ def testDlgAbout_NWDialog(qtbot, nwGUI):
|
|||||||
assert msgAbout.pageNotes.document().characterCount() > 100
|
assert msgAbout.pageNotes.document().characterCount() > 100
|
||||||
assert msgAbout.pageLicense.document().characterCount() > 100
|
assert msgAbout.pageLicense.document().characterCount() > 100
|
||||||
|
|
||||||
msgAbout.mainConf.assetPath = "whatever"
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr("novelwriter.config.Config.getAssetPath", lambda *a: Path("whatever"))
|
||||||
msgAbout._fillNotesPage()
|
msgAbout._fillNotesPage()
|
||||||
assert msgAbout.pageNotes.toPlainText() == "Error loading release notes text ..."
|
assert msgAbout.pageNotes.toPlainText() == "Error loading release notes text ..."
|
||||||
|
msgAbout._fillLicensePage()
|
||||||
msgAbout._fillLicensePage()
|
assert msgAbout.pageLicense.toPlainText() == "Error loading licence text ..."
|
||||||
assert msgAbout.pageLicense.toPlainText() == "Error loading licence text ..."
|
|
||||||
|
|
||||||
msgAbout.showReleaseNotes()
|
msgAbout.showReleaseNotes()
|
||||||
assert msgAbout.tabBox.currentWidget() == msgAbout.pageNotes
|
assert msgAbout.tabBox.currentWidget() == msgAbout.pageNotes
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
import shutil
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
from mock import causeOSError
|
from mock import causeOSError
|
||||||
@@ -38,7 +38,7 @@ from novelwriter.gui.theme import GuiIcons, GuiTheme
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testGuiTheme_Main(qtbot, nwGUI, fncDir):
|
def testGuiTheme_Main(qtbot, nwGUI, fncPath):
|
||||||
"""Test the theme class init.
|
"""Test the theme class init.
|
||||||
"""
|
"""
|
||||||
mainTheme: GuiTheme = nwGUI.mainTheme
|
mainTheme: GuiTheme = nwGUI.mainTheme
|
||||||
@@ -75,15 +75,15 @@ def testGuiTheme_Main(qtbot, nwGUI, fncDir):
|
|||||||
# Scan for Themes
|
# Scan for Themes
|
||||||
# ===============
|
# ===============
|
||||||
|
|
||||||
assert mainTheme._listConf({}, "not_a_path") is False
|
assert mainTheme._listConf({}, Path("not_a_path")) is False
|
||||||
|
|
||||||
themeOne = os.path.join(fncDir, "themes", "themeone.conf")
|
themeOne = fncPath / "themes" / "themeone.conf"
|
||||||
themeTwo = os.path.join(fncDir, "themes", "themetwo.conf")
|
themeTwo = fncPath / "themes" / "themetwo.conf"
|
||||||
writeFile(themeOne, "# Stuff")
|
writeFile(themeOne, "# Stuff")
|
||||||
writeFile(themeTwo, "# Stuff")
|
writeFile(themeTwo, "# Stuff")
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
assert mainTheme._listConf(result, os.path.join(fncDir, "themes")) is True
|
assert mainTheme._listConf(result, fncPath / "themes") is True
|
||||||
assert result["themeone"] == themeOne
|
assert result["themeone"] == themeOne
|
||||||
assert result["themetwo"] == themeTwo
|
assert result["themetwo"] == themeTwo
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ def testGuiTheme_Main(qtbot, nwGUI, fncDir):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncDir):
|
def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
|
||||||
"""Test the theme part of the class.
|
"""Test the theme part of the class.
|
||||||
"""
|
"""
|
||||||
mainTheme: GuiTheme = nwGUI.mainTheme
|
mainTheme: GuiTheme = nwGUI.mainTheme
|
||||||
@@ -132,15 +132,8 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncDir):
|
|||||||
# List Themes
|
# List Themes
|
||||||
# ===========
|
# ===========
|
||||||
|
|
||||||
shutil.copy(
|
shutil.copy(mainConf.getAssetPath("themes") / "default_dark.conf", fncPath / "themes")
|
||||||
os.path.join(mainConf.assetPath, "themes", "default_dark.conf"),
|
shutil.copy(mainConf.getAssetPath("themes") / "default.conf", fncPath / "themes")
|
||||||
os.path.join(fncDir, "themes")
|
|
||||||
)
|
|
||||||
shutil.copy(
|
|
||||||
os.path.join(mainConf.assetPath, "themes", "default.conf"),
|
|
||||||
os.path.join(fncDir, "themes")
|
|
||||||
)
|
|
||||||
writeFile(os.path.join(fncDir, "themes", "default.qss"), "/* Stuff */")
|
|
||||||
|
|
||||||
# Block the reading of the files
|
# Block the reading of the files
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
@@ -197,7 +190,7 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncDir):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncDir):
|
def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
|
||||||
"""Test the syntax part of the class.
|
"""Test the syntax part of the class.
|
||||||
"""
|
"""
|
||||||
mainTheme: GuiTheme = nwGUI.mainTheme
|
mainTheme: GuiTheme = nwGUI.mainTheme
|
||||||
@@ -206,14 +199,8 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncDir):
|
|||||||
# List Themes
|
# List Themes
|
||||||
# ===========
|
# ===========
|
||||||
|
|
||||||
shutil.copy(
|
shutil.copy(mainConf.getAssetPath("syntax") / "default_dark.conf", fncPath / "syntax")
|
||||||
os.path.join(mainConf.assetPath, "syntax", "default_dark.conf"),
|
shutil.copy(mainConf.getAssetPath("syntax") / "default_light.conf", fncPath / "syntax")
|
||||||
os.path.join(fncDir, "syntax")
|
|
||||||
)
|
|
||||||
shutil.copy(
|
|
||||||
os.path.join(mainConf.assetPath, "syntax", "default_light.conf"),
|
|
||||||
os.path.join(fncDir, "syntax")
|
|
||||||
)
|
|
||||||
|
|
||||||
# Block the reading of the files
|
# Block the reading of the files
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
@@ -270,11 +257,10 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncDir):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncDir):
|
def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncPath):
|
||||||
"""Test the icon cache class.
|
"""Test the icon cache class.
|
||||||
"""
|
"""
|
||||||
iconCache: GuiIcons = nwGUI.mainTheme.iconCache
|
iconCache: GuiIcons = nwGUI.mainTheme.iconCache
|
||||||
mainConf: Config = nwGUI.mainConf
|
|
||||||
|
|
||||||
# Load Theme
|
# Load Theme
|
||||||
# ==========
|
# ==========
|
||||||
@@ -288,10 +274,11 @@ def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncDir):
|
|||||||
assert iconCache.loadTheme("typicons_dark") is False
|
assert iconCache.loadTheme("typicons_dark") is False
|
||||||
|
|
||||||
# Load a broken theme file
|
# Load a broken theme file
|
||||||
iconsDir = os.path.join(fncDir, "icons")
|
iconsDir = fncPath / "icons"
|
||||||
os.mkdir(iconsDir)
|
testIcons = iconsDir / "testicons"
|
||||||
os.mkdir(os.path.join(iconsDir, "testicons"))
|
iconsDir.mkdir()
|
||||||
writeFile(os.path.join(iconsDir, "testicons", "icons.conf"), (
|
testIcons.mkdir()
|
||||||
|
writeFile(testIcons / "icons.conf", (
|
||||||
"[Main]\n"
|
"[Main]\n"
|
||||||
"name = Test Icons\n"
|
"name = Test Icons\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -300,15 +287,15 @@ def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncDir):
|
|||||||
"stuff = stuff.svg\n"
|
"stuff = stuff.svg\n"
|
||||||
))
|
))
|
||||||
|
|
||||||
assetPath = mainConf.assetPath
|
iconPath = iconCache._iconPath
|
||||||
mainConf.assetPath = fncDir
|
iconCache._iconPath = fncPath / "icons"
|
||||||
|
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
assert iconCache.loadTheme("testicons") is True
|
assert iconCache.loadTheme("testicons") is True
|
||||||
assert "Unknown icon name 'stuff' in config file" in caplog.text
|
assert "Unknown icon name 'stuff' in config file" in caplog.text
|
||||||
assert "Icon file 'add.svg' not in theme folder" in caplog.text
|
assert "Icon file 'add.svg' not in theme folder" in caplog.text
|
||||||
|
|
||||||
mainConf.assetPath = assetPath
|
iconCache._iconPath = iconPath
|
||||||
|
|
||||||
# Load working theme file
|
# Load working theme file
|
||||||
assert iconCache.loadTheme("typicons_dark") is True
|
assert iconCache.loadTheme("typicons_dark") is True
|
||||||
@@ -327,7 +314,7 @@ def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncDir):
|
|||||||
|
|
||||||
# Fail finding the file
|
# Fail finding the file
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("os.path.isfile", lambda *a: False)
|
mp.setattr("pathlib.Path.is_file", lambda *a: False)
|
||||||
qPix = iconCache.loadDecoration("wiz-back")
|
qPix = iconCache.loadDecoration("wiz-back")
|
||||||
assert qPix.isNull() is True
|
assert qPix.isNull() is True
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user