Switch to Path objects nearly everywhere
This commit is contained in:
+5
-28
@@ -23,12 +23,12 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import uuid
|
||||
import hashlib
|
||||
import logging
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from configparser import ConfigParser
|
||||
|
||||
@@ -36,7 +36,7 @@ from PyQt5.QtCore import QCoreApplication
|
||||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
||||
from novelwriter.error import formatException, logException
|
||||
from novelwriter.error import logException
|
||||
from novelwriter.constants import nwConst, nwUnicode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -458,20 +458,16 @@ def jsonEncode(data, n=0, nmax=0):
|
||||
def readTextFile(path):
|
||||
"""Read the content of a text file in a robust manner.
|
||||
"""
|
||||
if not os.path.isfile(path):
|
||||
path = Path(path)
|
||||
if not path.is_file():
|
||||
return ""
|
||||
|
||||
text = ""
|
||||
try:
|
||||
with open(path, mode="r", encoding="utf-8") as inFile:
|
||||
text = inFile.read()
|
||||
return path.read_text(encoding="utf-8")
|
||||
except Exception:
|
||||
logger.error("Could not read file: %s", path)
|
||||
logException()
|
||||
return ""
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def makeFileNameSafe(value):
|
||||
"""Returns a filename safe string of the value.
|
||||
@@ -483,25 +479,6 @@ def makeFileNameSafe(value):
|
||||
return clean
|
||||
|
||||
|
||||
def ensureFolder(path, parent=None, errLog=None):
|
||||
"""Make sure a folder exists, and if it doesn't, create it.
|
||||
"""
|
||||
try:
|
||||
if parent:
|
||||
path = os.path.join(parent, path)
|
||||
if not os.path.isdir(path):
|
||||
os.mkdir(path)
|
||||
except Exception as exc:
|
||||
logger.error("Could not create folder: %s", path)
|
||||
logException()
|
||||
if isinstance(errLog, list):
|
||||
errLog.append(f"Could not create folder: {path}")
|
||||
errLog.append(formatException(exc))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def sha256sum(path):
|
||||
"""Make a shasum of a file using a buffer.
|
||||
Based on: https://stackoverflow.com/a/44873382/5825851
|
||||
|
||||
+21
-5
@@ -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/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import logging
|
||||
@@ -184,7 +183,7 @@ class Config:
|
||||
self.searchMatchCap = False
|
||||
|
||||
# Backup Settings
|
||||
self.backupPath = ""
|
||||
self._backupPath = None
|
||||
self.backupOnClose = False
|
||||
self.askBeforeBackup = True
|
||||
|
||||
@@ -296,6 +295,14 @@ class Config:
|
||||
return self._lastPath
|
||||
return Path.home().absolute()
|
||||
|
||||
def backupPath(self):
|
||||
"""Return the backup path.
|
||||
"""
|
||||
if isinstance(self._backupPath, Path):
|
||||
if self._backupPath.is_dir():
|
||||
return self._backupPath
|
||||
return None
|
||||
|
||||
def errorText(self):
|
||||
"""Compile and return error messages from the initialisation of
|
||||
the Config class, and clear the error buffer.
|
||||
@@ -369,7 +376,7 @@ class Config:
|
||||
lngFile = "%s_%s" % (lngBase, lngCode.replace("-", "_"))
|
||||
if lngFile not in self._qtTrans:
|
||||
if qTrans.load(lngFile, str(lngPath)):
|
||||
logger.debug("Loaded: %s", os.path.join(lngPath, lngFile))
|
||||
logger.debug("Loaded: %s/%s", lngPath, lngFile)
|
||||
nwApp.installTranslator(qTrans)
|
||||
self._qtTrans[lngFile] = qTrans
|
||||
|
||||
@@ -489,9 +496,10 @@ class Config:
|
||||
|
||||
# Backup
|
||||
cnfSec = "Backup"
|
||||
self.backupPath = theConf.rdStr(cnfSec, "backuppath", self.backupPath)
|
||||
backupPath = theConf.rdStr(cnfSec, "backuppath", None)
|
||||
self.backupOnClose = theConf.rdBool(cnfSec, "backuponclose", self.backupOnClose)
|
||||
self.askBeforeBackup = theConf.rdBool(cnfSec, "askbeforebackup", self.askBeforeBackup)
|
||||
self.setBackupPath(backupPath)
|
||||
|
||||
# State
|
||||
cnfSec = "State"
|
||||
@@ -599,7 +607,7 @@ class Config:
|
||||
}
|
||||
|
||||
theConf["Backup"] = {
|
||||
"backuppath": str(self.backupPath),
|
||||
"backuppath": str(self._backupPath or ""),
|
||||
"backuponclose": str(self.backupOnClose),
|
||||
"askbeforebackup": str(self.askBeforeBackup),
|
||||
}
|
||||
@@ -653,6 +661,14 @@ class Config:
|
||||
logger.debug("Last path updated: %s" % self._lastPath)
|
||||
return
|
||||
|
||||
def setBackupPath(self, backupPath):
|
||||
"""Set the current backup path.
|
||||
"""
|
||||
self._backupPath = None
|
||||
if isinstance(backupPath, (str, Path)):
|
||||
self._backupPath = Path(backupPath)
|
||||
return
|
||||
|
||||
def setWinSize(self, newWidth, newHeight):
|
||||
"""Set the size of the main window, but only if the change is
|
||||
larger than 5 pixels. The OS window manager will sometimes
|
||||
|
||||
@@ -456,7 +456,8 @@ class NWProject(QObject):
|
||||
logger.info("Backing up project")
|
||||
self.mainGui.setStatus(self.tr("Backing up project ..."))
|
||||
|
||||
if not self.mainConf.backupPath:
|
||||
backupPath = self.mainConf.backupPath()
|
||||
if not isinstance(backupPath, Path):
|
||||
self.mainGui.makeAlert(self.tr(
|
||||
"Cannot backup project because no valid backup path is set. "
|
||||
"Please set a valid backup location in Preferences."
|
||||
@@ -471,7 +472,7 @@ class NWProject(QObject):
|
||||
return False
|
||||
|
||||
cleanName = makeFileNameSafe(self._data.name)
|
||||
baseDir = Path(self.mainConf.backupPath) / cleanName
|
||||
baseDir = backupPath / cleanName
|
||||
try:
|
||||
baseDir.mkdir(exist_ok=True)
|
||||
except Exception as exc:
|
||||
|
||||
@@ -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/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
import novelwriter
|
||||
|
||||
@@ -384,7 +383,7 @@ class GuiPreferencesProjects(QWidget):
|
||||
self.mainForm.addGroupLabel(self.tr("Project Backup"))
|
||||
|
||||
# Backup Path
|
||||
self.backupPath = self.mainConf.backupPath
|
||||
self.backupPath = self.mainConf.backupPath()
|
||||
self.backupGetPath = QPushButton(self.tr("Browse"))
|
||||
self.backupGetPath.clicked.connect(self._backupFolder)
|
||||
self.backupPathRow = self.mainForm.addRow(
|
||||
@@ -451,7 +450,7 @@ class GuiPreferencesProjects(QWidget):
|
||||
self.mainConf.autoSaveProj = self.autoSaveProj.value()
|
||||
|
||||
# Project Backup
|
||||
self.mainConf.backupPath = self.backupPath
|
||||
self.mainConf.setBackupPath(self.backupPath)
|
||||
self.mainConf.backupOnClose = self.backupOnClose.isChecked()
|
||||
self.mainConf.askBeforeBackup = self.askBeforeBackup.isChecked()
|
||||
|
||||
@@ -470,12 +469,9 @@ class GuiPreferencesProjects(QWidget):
|
||||
def _backupFolder(self):
|
||||
"""Open a dialog to select the backup folder.
|
||||
"""
|
||||
currDir = self.backupPath
|
||||
if not os.path.isdir(currDir):
|
||||
currDir = ""
|
||||
|
||||
currDir = self.backupPath or ""
|
||||
newDir = QFileDialog.getExistingDirectory(
|
||||
self, self.tr("Backup Directory"), currDir, options=QFileDialog.ShowDirsOnly
|
||||
self, self.tr("Backup Directory"), str(currDir), options=QFileDialog.ShowDirsOnly
|
||||
)
|
||||
if newDir:
|
||||
self.backupPath = newDir
|
||||
|
||||
@@ -23,10 +23,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/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
import novelwriter
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
from PyQt5.QtGui import QKeySequence
|
||||
@@ -190,8 +190,8 @@ class GuiProjectLoad(QDialog):
|
||||
self, self.tr("Open Project"), "", filter=";;".join(extFilter)
|
||||
)
|
||||
if projFile:
|
||||
thePath = os.path.abspath(os.path.dirname(projFile))
|
||||
self.selPath.setText(thePath)
|
||||
thePath = Path(projFile).absolute()
|
||||
self.selPath.setText(str(thePath))
|
||||
self.openPath = thePath
|
||||
self.openState = self.OPEN_STATE
|
||||
self.accept()
|
||||
|
||||
@@ -826,7 +826,7 @@ class GuiMainMenu(QMenuBar):
|
||||
|
||||
# Tools > Backup
|
||||
self.aBackupProject = QAction(self.tr("Backup Project"), self)
|
||||
self.aBackupProject.triggered.connect(lambda: self.theProject.backupProject(doNoify=True))
|
||||
self.aBackupProject.triggered.connect(lambda: self.theProject.backupProject(True))
|
||||
self.toolsMenu.addAction(self.aBackupProject)
|
||||
|
||||
# Tools > Export Project
|
||||
|
||||
@@ -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/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
import novelwriter
|
||||
|
||||
@@ -362,7 +361,7 @@ class GuiMain(QMainWindow):
|
||||
logger.error("No projData or projPath set")
|
||||
return False
|
||||
|
||||
if os.path.isfile(os.path.join(projPath, nwFiles.PROJ_FILE)):
|
||||
if (Path(projPath) / nwFiles.PROJ_FILE).is_file():
|
||||
self.makeAlert(self.tr(
|
||||
"A project already exists in that location. "
|
||||
"Please choose another folder."
|
||||
@@ -414,7 +413,7 @@ class GuiMain(QMainWindow):
|
||||
if not msgYes:
|
||||
doBackup = False
|
||||
if doBackup:
|
||||
self.theProject.backupProject(doNotify=False)
|
||||
self.theProject.backupProject(False)
|
||||
else:
|
||||
saveOK = True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user