Optimise a few details and add some tests
This commit is contained in:
@@ -436,9 +436,9 @@ def describeFont(font: QFont) -> str:
|
|||||||
|
|
||||||
def fontMatcher(font: QFont) -> QFont:
|
def fontMatcher(font: QFont) -> QFont:
|
||||||
"""Make sure the font is the correct family, if possible. This
|
"""Make sure the font is the correct family, if possible. This
|
||||||
ensures that Qt doesn't reuse another font under the hood. The
|
ensures that Qt doesn't re-use another font under the hood. The
|
||||||
default Qt5 font matching algorithm doesn't handle well changing
|
default Qt5 font matching algorithm doesn't handle well changing
|
||||||
fonts at runtime.
|
application fonts at runtime.
|
||||||
"""
|
"""
|
||||||
info = QFontInfo(font)
|
info = QFontInfo(font)
|
||||||
if (famRequest := font.family()) != (famActual := info.family()):
|
if (famRequest := font.family()) != (famActual := info.family()):
|
||||||
@@ -448,6 +448,7 @@ def fontMatcher(font: QFont) -> QFont:
|
|||||||
styleRequest, sizeRequest = font.styleName(), font.pointSize()
|
styleRequest, sizeRequest = font.styleName(), font.pointSize()
|
||||||
logger.info("Lookup: %s, %s, %d pt", famRequest, styleRequest, sizeRequest)
|
logger.info("Lookup: %s, %s, %d pt", famRequest, styleRequest, sizeRequest)
|
||||||
temp = db.font(famRequest, styleRequest, sizeRequest)
|
temp = db.font(famRequest, styleRequest, sizeRequest)
|
||||||
|
temp.setPointSize(sizeRequest) # Make sure it isn't changed
|
||||||
famFound, styleFound, sizeFound = temp.family(), temp.styleName(), temp.pointSize()
|
famFound, styleFound, sizeFound = temp.family(), temp.styleName(), temp.pointSize()
|
||||||
if famFound == famRequest:
|
if famFound == famRequest:
|
||||||
logger.info("Found: %s, %s, %d pt", famFound, styleFound, sizeFound)
|
logger.info("Found: %s, %s, %d pt", famFound, styleFound, sizeFound)
|
||||||
@@ -464,6 +465,12 @@ def qtLambda(func: Callable, *args: Any, **kwargs: Any) -> Callable:
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def encodeMimeHandles(mimeData: QMimeData, handles: list[str]) -> None:
|
||||||
|
"""Encode handles into a mime data object."""
|
||||||
|
mimeData.setData(nwConst.MIME_HANDLE, b"|".join(h.encode() for h in handles))
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def decodeMimeHandles(mimeData: QMimeData) -> list[str]:
|
def decodeMimeHandles(mimeData: QMimeData) -> list[str]:
|
||||||
"""Decode and split a mime data object with handles."""
|
"""Decode and split a mime data object with handles."""
|
||||||
return mimeData.data(nwConst.MIME_HANDLE).data().decode().split("|")
|
return mimeData.data(nwConst.MIME_HANDLE).data().decode().split("|")
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ from typing import TYPE_CHECKING
|
|||||||
from PyQt5.QtCore import QAbstractItemModel, QMimeData, QModelIndex, Qt
|
from PyQt5.QtCore import QAbstractItemModel, QMimeData, QModelIndex, Qt
|
||||||
from PyQt5.QtGui import QFont, QIcon
|
from PyQt5.QtGui import QFont, QIcon
|
||||||
|
|
||||||
from novelwriter.common import decodeMimeHandles, minmax
|
from novelwriter.common import decodeMimeHandles, encodeMimeHandles, minmax
|
||||||
from novelwriter.constants import nwConst
|
from novelwriter.constants import nwConst
|
||||||
from novelwriter.core.item import NWItem
|
from novelwriter.core.item import NWItem
|
||||||
from novelwriter.enum import nwItemClass
|
from novelwriter.enum import nwItemClass
|
||||||
@@ -367,11 +367,11 @@ class ProjectModel(QAbstractItemModel):
|
|||||||
def mimeData(self, indices: list[QModelIndex]) -> QMimeData:
|
def mimeData(self, indices: list[QModelIndex]) -> QMimeData:
|
||||||
"""Encode mime data about a selection."""
|
"""Encode mime data about a selection."""
|
||||||
handles = [
|
handles = [
|
||||||
i.internalPointer().item.itemHandle.encode()
|
i.internalPointer().item.itemHandle
|
||||||
for i in indices if i.isValid() and i.column() == 0
|
for i in indices if i.isValid() and i.column() == 0
|
||||||
]
|
]
|
||||||
mime = QMimeData()
|
mime = QMimeData()
|
||||||
mime.setData(nwConst.MIME_HANDLE, b"|".join(handles))
|
encodeMimeHandles(mime, handles)
|
||||||
return mime
|
return mime
|
||||||
|
|
||||||
def canDropMimeData(
|
def canDropMimeData(
|
||||||
|
|||||||
@@ -1279,11 +1279,13 @@ class GuiDocEditor(QPlainTextEdit):
|
|||||||
"""Process the word counter's finished signal."""
|
"""Process the word counter's finished signal."""
|
||||||
if self._docHandle and self._nwItem:
|
if self._docHandle and self._nwItem:
|
||||||
logger.debug("Updating word count")
|
logger.debug("Updating word count")
|
||||||
|
needsRefresh = wCount != self._nwItem.wordCount
|
||||||
self._nwItem.setCharCount(cCount)
|
self._nwItem.setCharCount(cCount)
|
||||||
self._nwItem.setWordCount(wCount)
|
self._nwItem.setWordCount(wCount)
|
||||||
self._nwItem.setParaCount(pCount)
|
self._nwItem.setParaCount(pCount)
|
||||||
self._nwItem.notifyToRefresh()
|
if needsRefresh:
|
||||||
self.docFooter.updateWordCount(wCount, False)
|
self._nwItem.notifyToRefresh()
|
||||||
|
self.docFooter.updateWordCount(wCount, False)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
|||||||
@@ -27,18 +27,19 @@ from xml.etree import ElementTree as ET
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QMimeData, QUrl
|
||||||
from PyQt5.QtGui import QColor, QDesktopServices, QFontDatabase
|
from PyQt5.QtGui import QColor, QDesktopServices, QFont, QFontDatabase, QFontInfo
|
||||||
|
|
||||||
from novelwriter.common import (
|
from novelwriter.common import (
|
||||||
NWConfigParser, checkBool, checkFloat, checkInt, checkIntTuple, checkPath,
|
NWConfigParser, checkBool, checkFloat, checkInt, checkIntTuple, checkPath,
|
||||||
checkString, checkStringNone, checkUuid, compact, cssCol, describeFont,
|
checkString, checkStringNone, checkUuid, compact, cssCol,
|
||||||
elide, firstFloat, formatFileFilter, formatInt, formatTime,
|
decodeMimeHandles, describeFont, elide, encodeMimeHandles, firstFloat,
|
||||||
formatTimeStamp, formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle,
|
fontMatcher, formatFileFilter, formatInt, formatTime, formatTimeStamp,
|
||||||
isItemClass, isItemLayout, isItemType, isListInstance, isTitleTag,
|
formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass,
|
||||||
jsonEncode, makeFileNameSafe, minmax, numberToRoman, openExternalPath,
|
isItemLayout, isItemType, isListInstance, isTitleTag, jsonEncode,
|
||||||
readTextFile, simplified, transferCase, uniqueCompact, xmlElement,
|
makeFileNameSafe, minmax, numberToRoman, openExternalPath, readTextFile,
|
||||||
xmlIndent, xmlSubElem, yesNo
|
simplified, transferCase, uniqueCompact, xmlElement, xmlIndent, xmlSubElem,
|
||||||
|
yesNo
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.mocked import causeOSError
|
from tests.mocked import causeOSError
|
||||||
@@ -528,6 +529,34 @@ def testBaseCommon_describeFont():
|
|||||||
assert describeFont(None) == "Error" # type: ignore
|
assert describeFont(None) == "Error" # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.base
|
||||||
|
def testBaseCommon_fontMatcher(monkeypatch):
|
||||||
|
"""Test the fontMatcher function."""
|
||||||
|
# Nonsense font is just returned
|
||||||
|
nonsense = QFont("nonesense", 10)
|
||||||
|
assert fontMatcher(nonsense) is nonsense
|
||||||
|
|
||||||
|
# General font
|
||||||
|
fontDB = QFontDatabase()
|
||||||
|
if len(fontDB.families()) > 1:
|
||||||
|
fontOne = QFont(fontDB.families()[0])
|
||||||
|
fontTwo = QFont(fontDB.families()[1])
|
||||||
|
check = QFont(fontOne)
|
||||||
|
check.setFamily(fontTwo.family())
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(QFontInfo, "family", lambda *a: "nonesense")
|
||||||
|
assert fontMatcher(check).family() == fontTwo.family()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.base
|
||||||
|
def testBaseCommon_encodeDecodeMimeHandles(monkeypatch):
|
||||||
|
"""Test the encodeMimeHandles and decodeMimeHandles functions."""
|
||||||
|
handles = ["0123456789abc", "123456789abcd", "23456789abcde"]
|
||||||
|
mimeData = QMimeData()
|
||||||
|
encodeMimeHandles(mimeData, handles)
|
||||||
|
assert decodeMimeHandles(mimeData) == handles
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.base
|
@pytest.mark.base
|
||||||
def testBaseCommon_jsonEncode():
|
def testBaseCommon_jsonEncode():
|
||||||
"""Test the jsonEncode function."""
|
"""Test the jsonEncode function."""
|
||||||
|
|||||||
Reference in New Issue
Block a user