From 864172ea508a4bcfeff353a7a2e56e8df283a28d Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 28 Apr 2024 18:22:31 +0200 Subject: [PATCH] Add an elide function for shortening text --- novelwriter/common.py | 9 ++++++++- novelwriter/gui/itemdetails.py | 14 ++++++-------- tests/test_base/test_base_common.py | 27 ++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/novelwriter/common.py b/novelwriter/common.py index 8f0ffcff..8573c1bd 100644 --- a/novelwriter/common.py +++ b/novelwriter/common.py @@ -40,7 +40,7 @@ from PyQt5.QtCore import QCoreApplication, QUrl from PyQt5.QtGui import QColor, QDesktopServices from novelwriter.constants import nwConst, nwLabels, nwUnicode, trConst -from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout +from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType from novelwriter.error import logException if TYPE_CHECKING: # pragma: no cover @@ -279,6 +279,13 @@ def simplified(text: str) -> str: return " ".join(str(text).strip().split()) +def elide(text: str, length: int) -> str: + """Elide a piece of text to a maximum length.""" + if len(text) > (cut := max(4, length)): + return f"{text[:cut-4].rstrip()} ..." + return text + + def yesNo(value: int | bool | None) -> Literal["yes", "no"]: """Convert a boolean evaluated variable to a yes or no.""" return "yes" if value else "no" diff --git a/novelwriter/gui/itemdetails.py b/novelwriter/gui/itemdetails.py index 1a90d2a3..486acf29 100644 --- a/novelwriter/gui/itemdetails.py +++ b/novelwriter/gui/itemdetails.py @@ -26,12 +26,14 @@ from __future__ import annotations import logging from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel +from PyQt5.QtWidgets import QGridLayout, QLabel, QWidget from novelwriter import CONFIG, SHARED -from novelwriter.constants import trConst, nwLabels +from novelwriter.common import elide +from novelwriter.constants import nwLabels, trConst from novelwriter.types import ( - QtAlignLeft, QtAlignLeftBase, QtAlignRight, QtAlignRightBase, QtAlignRightMiddle + QtAlignLeft, QtAlignLeftBase, QtAlignRight, QtAlignRightBase, + QtAlignRightMiddle ) logger = logging.getLogger(__name__) @@ -236,10 +238,6 @@ class GuiItemDetails(QWidget): # Label # ===== - label = nwItem.itemName - if len(label) > 100: - label = label[:96].rstrip()+" ..." - if nwItem.isFileType(): if nwItem.isActive: self.labelIcon.setPixmap(SHARED.theme.getPixmap("checked", (iPx, iPx))) @@ -248,7 +246,7 @@ class GuiItemDetails(QWidget): else: self.labelIcon.setPixmap(SHARED.theme.getPixmap("noncheckable", (iPx, iPx))) - self.labelData.setText(label) + self.labelData.setText(elide(nwItem.itemName, 100)) # Status # ====== diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py index b97d3f7f..dfe5cdb0 100644 --- a/tests/test_base/test_base_common.py +++ b/tests/test_base/test_base_common.py @@ -27,14 +27,12 @@ from xml.etree import ElementTree as ET import pytest -from mocked import causeOSError from PyQt5.QtCore import QUrl from PyQt5.QtGui import QColor, QDesktopServices -from tools import writeFile from novelwriter.common import ( NWConfigParser, checkBool, checkFloat, checkInt, checkIntTuple, checkPath, - checkString, checkStringNone, checkUuid, cssCol, formatFileFilter, + checkString, checkStringNone, checkUuid, cssCol, elide, formatFileFilter, formatInt, formatTime, formatTimeStamp, formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, isItemLayout, isItemType, isListInstance, isTitleTag, jsonEncode, makeFileNameSafe, minmax, @@ -42,6 +40,9 @@ from novelwriter.common import ( xmlIndent, yesNo ) +from tests.mocked import causeOSError +from tests.tools import writeFile + @pytest.mark.base def testBaseCommon_checkStringNone(): @@ -387,6 +388,26 @@ def testBaseCommon_simplified(): # END Test testBaseCommon_simplified +@pytest.mark.base +def testBaseCommon_elide(): + """Test the elide function.""" + assert elide("Hello World!", 12) == "Hello World!" + assert elide("Hello World!", 11) == "Hello W ..." + assert elide("Hello World!", 10) == "Hello ..." + assert elide("Hello World!", 9) == "Hello ..." + assert elide("Hello World!", 8) == "Hell ..." + assert elide("Hello World!", 7) == "Hel ..." + assert elide("Hello World!", 6) == "He ..." + assert elide("Hello World!", 5) == "H ..." + assert elide("Hello World!", 4) == " ..." + assert elide("Hello World!", 3) == " ..." + assert elide("Hello World!", 2) == " ..." + assert elide("Hello World!", 1) == " ..." + assert elide("Hello World!", 0) == " ..." + +# END Test testBaseCommon_elide + + @pytest.mark.base def testBaseCommon_yesNo(): """Test the yesNo function."""