Optimise a few details and add some tests

This commit is contained in:
Veronica Berglyd Olsen
2024-11-26 17:07:02 +01:00
parent c091e0b9bb
commit 43d95462e0
4 changed files with 54 additions and 16 deletions
+9 -2
View File
@@ -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("|")
+3 -3
View File
@@ -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(
+4 -2
View File
@@ -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()
+38 -9
View File
@@ -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."""