Copy changes from download_dicts branch

This commit is contained in:
Veronica Berglyd Olsen
2023-11-20 17:24:49 +01:00
parent c585c87633
commit e00e64dc46
10 changed files with 176 additions and 18 deletions
+8
View File
@@ -487,6 +487,14 @@ def makeFileNameSafe(text: str) -> str:
return "".join(c for c in text if c.isalnum() or c in allowed) return "".join(c for c in text if c.isalnum() or c in allowed)
def getFileSize(path: Path) -> int:
"""Return the size of a file."""
try:
return path.stat().st_size
except Exception:
return -1
# =============================================================================================== # # =============================================================================================== #
# Other Functions # Other Functions
# =============================================================================================== # # =============================================================================================== #
+2
View File
@@ -225,6 +225,7 @@ class Config:
# Other System Info # Other System Info
self.hostName = QSysInfo.machineHostName() self.hostName = QSysInfo.machineHostName()
self.kernelVer = QSysInfo.kernelVersion() self.kernelVer = QSysInfo.kernelVersion()
self.isDebug = False
# Packages # Packages
self.hasEnchant = False # The pyenchant package self.hasEnchant = False # The pyenchant package
@@ -484,6 +485,7 @@ class Config:
self._recentObj.loadCache() self._recentObj.loadCache()
self._checkOptionalPackages() self._checkOptionalPackages()
self.isDebug = logger.getEffectiveLevel() == logging.DEBUG
logger.debug("Config instance initialised") logger.debug("Config instance initialised")
+3
View File
@@ -50,6 +50,9 @@ class nwConst:
URL_HELP = "https://github.com/vkbo/novelWriter/discussions" URL_HELP = "https://github.com/vkbo/novelWriter/discussions"
URL_RELEASE = "https://github.com/vkbo/novelWriter/releases/latest" URL_RELEASE = "https://github.com/vkbo/novelWriter/releases/latest"
# Requests
USER_AGENT = "Mozilla/5.0 (compatible; novelWriter (Python))"
# Gui Settings # Gui Settings
STATUS_MSG_TIMEOUT = 15000 # milliseconds STATUS_MSG_TIMEOUT = 15000 # milliseconds
+25 -14
View File
@@ -29,10 +29,10 @@ import logging
from datetime import datetime from datetime import datetime
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
from PyQt5.QtGui import QCursor from PyQt5.QtGui import QCloseEvent, QCursor
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
qApp, QDialog, QHBoxLayout, QVBoxLayout, QDialogButtonBox, QLabel QWidget, qApp, QDialog, QHBoxLayout, QVBoxLayout, QDialogButtonBox, QLabel
) )
from novelwriter import CONFIG, SHARED, __version__, __date__ from novelwriter import CONFIG, SHARED, __version__, __date__
@@ -44,8 +44,8 @@ logger = logging.getLogger(__name__)
class GuiUpdates(QDialog): class GuiUpdates(QDialog):
def __init__(self, mainGui): def __init__(self, parent: QWidget) -> None:
super().__init__(parent=mainGui) super().__init__(parent=parent)
logger.debug("Create: GuiUpdates") logger.debug("Create: GuiUpdates")
self.setObjectName("GuiUpdates") self.setObjectName("GuiUpdates")
@@ -94,8 +94,8 @@ class GuiUpdates(QDialog):
self.latestLabel.setFont(hFont) self.latestLabel.setFont(hFont)
# Buttons # Buttons
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
self.buttonBox.accepted.connect(self._doClose) self.buttonBox.rejected.connect(self._doClose)
# Assemble # Assemble
self.innerBox = QHBoxLayout() self.innerBox = QHBoxLayout()
@@ -114,17 +114,16 @@ class GuiUpdates(QDialog):
return return
def __del__(self): # pragma: no cover def __del__(self) -> None: # pragma: no cover
logger.debug("Delete: GuiUpdates") logger.debug("Delete: GuiUpdates")
return return
def checkLatest(self): def checkLatest(self) -> None:
"""Check for latest release. """Check for latest release."""
"""
qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
urlReq = Request("https://api.github.com/repos/vkbo/novelwriter/releases/latest") urlReq = Request("https://api.github.com/repos/vkbo/novelwriter/releases/latest")
urlReq.add_header("User-Agent", "Mozilla/5.0 (compatible; novelWriter (Python))") urlReq.add_header("User-Agent", nwConst.USER_AGENT)
urlReq.add_header("Accept", "application/vnd.github.v3+json") urlReq.add_header("Accept", "application/vnd.github.v3+json")
rawData = {} rawData = {}
@@ -161,10 +160,22 @@ class GuiUpdates(QDialog):
return return
## ##
# Internal Functions # Events
## ##
def _doClose(self): def closeEvent(self, event: QCloseEvent) -> None:
"""Capture the user closing the window."""
event.accept()
self.deleteLater()
return
##
# Private Slots
##
@pyqtSlot()
def _doClose(self) -> None:
"""Close the dialog."""
self.close() self.close()
return return
+1 -1
View File
@@ -620,7 +620,7 @@ class GuiDocViewHistory:
"""Debug function to dump history to the logger. Since it is a """Debug function to dump history to the logger. Since it is a
for loop, it is skipped entirely if log level isn't DEBUG. for loop, it is skipped entirely if log level isn't DEBUG.
""" """
if logger.getEffectiveLevel() == logging.DEBUG: # pragma: no cover if CONFIG.isDebug: # pragma: no cover
for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory)): for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory)):
logger.debug( logger.debug(
"History %02d: %s %13s [x:%d]" % ( "History %02d: %s %13s [x:%d]" % (
+5
View File
@@ -870,6 +870,11 @@ class GuiMainMenu(QMenuBar):
self.aEditWordList = self.toolsMenu.addAction(self.tr("Project Word List")) self.aEditWordList = self.toolsMenu.addAction(self.tr("Project Word List"))
self.aEditWordList.triggered.connect(lambda: self.mainGui.showProjectWordListDialog()) self.aEditWordList.triggered.connect(lambda: self.mainGui.showProjectWordListDialog())
# Tools > Add Dictionaries
if CONFIG.osWindows or CONFIG.isDebug:
self.aAddDicts = self.toolsMenu.addAction(self.tr("Add Dictionaries"))
self.aAddDicts.triggered.connect(self.mainGui.showDictionariesDialog)
# Tools > Separator # Tools > Separator
self.toolsMenu.addSeparator() self.toolsMenu.addSeparator()
+16 -1
View File
@@ -59,6 +59,7 @@ from novelwriter.dialogs.projsettings import GuiProjectSettings
from novelwriter.tools.lipsum import GuiLipsum from novelwriter.tools.lipsum import GuiLipsum
from novelwriter.tools.manuscript import GuiManuscript from novelwriter.tools.manuscript import GuiManuscript
from novelwriter.tools.projwizard import GuiProjectWizard from novelwriter.tools.projwizard import GuiProjectWizard
from novelwriter.tools.dictionaries import GuiDictionaries
from novelwriter.tools.writingstats import GuiWritingStats from novelwriter.tools.writingstats import GuiWritingStats
from novelwriter.core.coretools import ProjectBuilder from novelwriter.core.coretools import ProjectBuilder
@@ -340,7 +341,7 @@ class GuiMain(QMainWindow):
logger.debug("Ready: GUI") logger.debug("Ready: GUI")
if __hexversion__[-2] == "a" and logger.getEffectiveLevel() > logging.DEBUG: if __hexversion__[-2] == "a" and not CONFIG.isDebug:
SHARED.warn(self.tr( SHARED.warn(self.tr(
"You are running an untested development version of novelWriter. " "You are running an untested development version of novelWriter. "
"Please be careful when working on a live project " "Please be careful when working on a live project "
@@ -1065,6 +1066,20 @@ class GuiMain(QMainWindow):
return return
@pyqtSlot()
def showDictionariesDialog(self) -> None:
"""Show the download dictionaries dialog."""
dlgDicts = GuiDictionaries(self)
dlgDicts.setModal(True)
dlgDicts.show()
dlgDicts.raise_()
qApp.processEvents()
if not dlgDicts.initDialog():
dlgDicts.close()
SHARED.error(self.tr("Could not initialise the dialog."))
return
def reportConfErr(self) -> bool: def reportConfErr(self) -> bool:
"""Checks if the Config module has any errors to report, and let """Checks if the Config module has any errors to report, and let
the user know if this is the case. The Config module caches the user know if this is the case. The Config module caches
+112
View File
@@ -0,0 +1,112 @@
"""
novelWriter GUI Dictionary Downloader
=======================================
File History:
Created: 2023-11-19 [2.2rc1]
This file is a part of novelWriter
Copyright 20182023, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import logging
from pathlib import Path
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import (
QDialog, QDialogButtonBox, QVBoxLayout, QWidget
)
from novelwriter import CONFIG
logger = logging.getLogger(__name__)
class GuiDictionaries(QDialog):
C_CODE = 0
C_NAME = 1
C_STATE = 2
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
logger.debug("Create: GuiDictionaries")
self.setObjectName("GuiDictionaries")
self.setWindowTitle(self.tr("Add Dictionaries"))
sPx = CONFIG.pxInt(16)
self.setMinimumWidth(CONFIG.pxInt(500))
self.setMinimumHeight(CONFIG.pxInt(200))
# Buttons
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
self.buttonBox.rejected.connect(self._doClose)
# Assemble
self.outerBox = QVBoxLayout()
self.outerBox.addWidget(self.buttonBox)
self.outerBox.setSpacing(sPx)
self.setLayout(self.outerBox)
logger.debug("Ready: GuiDictionaries")
return
def __del__(self) -> None: # pragma: no cover
logger.debug("Delete: GuiDictionaries")
return
def initDialog(self) -> bool:
"""Prepare and check that we can proceed."""
try:
import enchant
path = Path(enchant.get_user_config_dir())
except Exception:
logger.error("Could not get enchant path")
return False
if path.is_dir():
pass
return True
##
# Events
##
def closeEvent(self, event: QCloseEvent) -> None:
"""Capture the user closing the window."""
event.accept()
self.deleteLater()
return
##
# Private Slots
##
@pyqtSlot()
def _doClose(self) -> None:
"""Close the dialog."""
self.close()
return
# END Class GuiDictionaries
+3 -2
View File
@@ -27,6 +27,7 @@ import logging
from pathlib import Path from pathlib import Path
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFileDialog, QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFileDialog,
@@ -227,7 +228,7 @@ class GuiManuscriptBuild(QDialog):
return return
def __del__(self): # pragma: no cover def __del__(self) -> None: # pragma: no cover
logger.debug("Delete: GuiManuscriptBuild") logger.debug("Delete: GuiManuscriptBuild")
return return
@@ -235,7 +236,7 @@ class GuiManuscriptBuild(QDialog):
# Events # Events
## ##
def closeEvent(self, event): def closeEvent(self, event: QCloseEvent) -> None:
"""Capture the user closing the window so we can save GUI """Capture the user closing the window so we can save GUI
settings. settings.
""" """
+1
View File
@@ -159,6 +159,7 @@ def nwGUI(qtbot, monkeypatch, functionFixture):
nwGUI = main(["--testmode", f"--config={_TMP_CONF}", f"--data={_TMP_CONF}"]) nwGUI = main(["--testmode", f"--config={_TMP_CONF}", f"--data={_TMP_CONF}"])
qtbot.addWidget(nwGUI) qtbot.addWidget(nwGUI)
resetConfigVars() resetConfigVars()
SHARED._alert = None
nwGUI.docEditor.initEditor() nwGUI.docEditor.initEditor()
nwGUI.show() nwGUI.show()