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:
|
||||
"""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
|
||||
fonts at runtime.
|
||||
application fonts at runtime.
|
||||
"""
|
||||
info = QFontInfo(font)
|
||||
if (famRequest := font.family()) != (famActual := info.family()):
|
||||
@@ -448,6 +448,7 @@ def fontMatcher(font: QFont) -> QFont:
|
||||
styleRequest, sizeRequest = font.styleName(), font.pointSize()
|
||||
logger.info("Lookup: %s, %s, %d pt", 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()
|
||||
if famFound == famRequest:
|
||||
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
|
||||
|
||||
|
||||
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]:
|
||||
"""Decode and split a mime data object with handles."""
|
||||
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.QtGui import QFont, QIcon
|
||||
|
||||
from novelwriter.common import decodeMimeHandles, minmax
|
||||
from novelwriter.common import decodeMimeHandles, encodeMimeHandles, minmax
|
||||
from novelwriter.constants import nwConst
|
||||
from novelwriter.core.item import NWItem
|
||||
from novelwriter.enum import nwItemClass
|
||||
@@ -367,11 +367,11 @@ class ProjectModel(QAbstractItemModel):
|
||||
def mimeData(self, indices: list[QModelIndex]) -> QMimeData:
|
||||
"""Encode mime data about a selection."""
|
||||
handles = [
|
||||
i.internalPointer().item.itemHandle.encode()
|
||||
i.internalPointer().item.itemHandle
|
||||
for i in indices if i.isValid() and i.column() == 0
|
||||
]
|
||||
mime = QMimeData()
|
||||
mime.setData(nwConst.MIME_HANDLE, b"|".join(handles))
|
||||
encodeMimeHandles(mime, handles)
|
||||
return mime
|
||||
|
||||
def canDropMimeData(
|
||||
|
||||
@@ -1279,11 +1279,13 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
"""Process the word counter's finished signal."""
|
||||
if self._docHandle and self._nwItem:
|
||||
logger.debug("Updating word count")
|
||||
needsRefresh = wCount != self._nwItem.wordCount
|
||||
self._nwItem.setCharCount(cCount)
|
||||
self._nwItem.setWordCount(wCount)
|
||||
self._nwItem.setParaCount(pCount)
|
||||
self._nwItem.notifyToRefresh()
|
||||
self.docFooter.updateWordCount(wCount, False)
|
||||
if needsRefresh:
|
||||
self._nwItem.notifyToRefresh()
|
||||
self.docFooter.updateWordCount(wCount, False)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
|
||||
@@ -27,18 +27,19 @@ from xml.etree import ElementTree as ET
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtCore import QUrl
|
||||
from PyQt5.QtGui import QColor, QDesktopServices, QFontDatabase
|
||||
from PyQt5.QtCore import QMimeData, QUrl
|
||||
from PyQt5.QtGui import QColor, QDesktopServices, QFont, QFontDatabase, QFontInfo
|
||||
|
||||
from novelwriter.common import (
|
||||
NWConfigParser, checkBool, checkFloat, checkInt, checkIntTuple, checkPath,
|
||||
checkString, checkStringNone, checkUuid, compact, cssCol, describeFont,
|
||||
elide, firstFloat, formatFileFilter, formatInt, formatTime,
|
||||
formatTimeStamp, formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle,
|
||||
isItemClass, isItemLayout, isItemType, isListInstance, isTitleTag,
|
||||
jsonEncode, makeFileNameSafe, minmax, numberToRoman, openExternalPath,
|
||||
readTextFile, simplified, transferCase, uniqueCompact, xmlElement,
|
||||
xmlIndent, xmlSubElem, yesNo
|
||||
checkString, checkStringNone, checkUuid, compact, cssCol,
|
||||
decodeMimeHandles, describeFont, elide, encodeMimeHandles, firstFloat,
|
||||
fontMatcher, formatFileFilter, formatInt, formatTime, formatTimeStamp,
|
||||
formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass,
|
||||
isItemLayout, isItemType, isListInstance, isTitleTag, jsonEncode,
|
||||
makeFileNameSafe, minmax, numberToRoman, openExternalPath, readTextFile,
|
||||
simplified, transferCase, uniqueCompact, xmlElement, xmlIndent, xmlSubElem,
|
||||
yesNo
|
||||
)
|
||||
|
||||
from tests.mocked import causeOSError
|
||||
@@ -528,6 +529,34 @@ def testBaseCommon_describeFont():
|
||||
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
|
||||
def testBaseCommon_jsonEncode():
|
||||
"""Test the jsonEncode function."""
|
||||
|
||||
Reference in New Issue
Block a user