Skip to content

Commit

Permalink
Add formatter helper for file extensions filters (#1693)
Browse files Browse the repository at this point in the history
  • Loading branch information
vkbo committed Feb 11, 2024
2 parents 81a9d51 + 701fe29 commit fb92c6c
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 30 deletions.
15 changes: 14 additions & 1 deletion novelwriter/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
from novelwriter.error import logException
from novelwriter.constants import nwConst, nwUnicode
from novelwriter.constants import nwConst, nwLabels, nwUnicode, trConst

if TYPE_CHECKING: # pragma: no cover
from typing import TypeGuard # Requires Python 3.10
Expand Down Expand Up @@ -248,6 +248,19 @@ def formatVersion(value: str) -> str:
return value.lower().replace("a", " Alpha ").replace("b", " Beta ").replace("rc", " RC ")


def formatFileFilter(extensions: list[str | tuple[str, str]]) -> str:
"""Format a list of extensions, or extension + label pairs into a
QFileDialog extensions filter.
"""
result = []
for ext in extensions:
if isinstance(ext, str):
result.append(f"{trConst(nwLabels.FILE_FILTERS.get(ext))} ({ext})")
elif isinstance(ext, tuple) and len(ext) == 2:
result.append(f"{ext[0]} ({ext[1]})")
return ";;".join(result)


##
# String Functions
##
Expand Down
6 changes: 6 additions & 0 deletions novelwriter/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,12 @@ class nwLabels:
nwBuildFmt.J_HTML: ".json",
nwBuildFmt.J_NWD: ".json",
}
FILE_FILTERS = {
"*.txt": QT_TRANSLATE_NOOP("Constant", "Text files"),
"*.md": QT_TRANSLATE_NOOP("Constant", "Markdown files"),
"*.nwd": QT_TRANSLATE_NOOP("Constant", "novelWriter files"),
"*": QT_TRANSLATE_NOOP("Constant", "All files"),
}
UNIT_NAME = {
"mm": QT_TRANSLATE_NOOP("Constant", "Millimetres"),
"cm": QT_TRANSLATE_NOOP("Constant", "Centimetres"),
Expand Down
8 changes: 3 additions & 5 deletions novelwriter/dialogs/wordlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
)

from novelwriter import CONFIG, SHARED
from novelwriter.common import formatFileFilter
from novelwriter.core.spellcheck import UserDictionary
from novelwriter.extensions.configlayout import NColourLabel

Expand Down Expand Up @@ -184,12 +185,9 @@ def _importWords(self) -> None:
SHARED.info(self.tr(
"Note: The import file must be a plain text file with UTF-8 or ASCII encoding."
))
extFilter = [
"{0} (*.txt)".format(self.tr("Text files")),
"{0} (*)".format(self.tr("All files")),
]
ffilter = formatFileFilter(["*.txt", "*"])
path, _ = QFileDialog.getOpenFileName(
self, self.tr("Import File"), str(Path.home()), filter=";;".join(extFilter)
self, self.tr("Import File"), str(Path.home()), filter=ffilter
)
if path:
try:
Expand Down
11 changes: 3 additions & 8 deletions novelwriter/guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
from novelwriter.enum import (
nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwWidget, nwView
)
from novelwriter.common import hexToInt
from novelwriter.common import formatFileFilter, hexToInt

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -664,14 +664,9 @@ def importDocument(self) -> bool:
return False

lastPath = CONFIG.lastPath()
extFilter = [
"{0} (*.txt)".format(self.tr("Text files")),
"{0} (*.md)".format(self.tr("Markdown files")),
"{0} (*.nwd)".format(self.tr("novelWriter files")),
"{0} (*)".format(self.tr("All files")),
]
ffilter = formatFileFilter(["*.txt", "*.md", "*.nwd", "*"])
loadFile, _ = QFileDialog.getOpenFileName(
self, self.tr("Import File"), str(lastPath), filter=";;".join(extFilter)
self, self.tr("Import File"), str(lastPath), filter=ffilter
)
if not loadFile:
return False
Expand Down
8 changes: 4 additions & 4 deletions novelwriter/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QWidget
from novelwriter.common import formatFileFilter

from novelwriter.constants import nwFiles
from novelwriter.core.spellcheck import NWSpellEnchant
Expand Down Expand Up @@ -221,13 +222,12 @@ def runInThreadPool(self, runnable: QRunnable, priority: int = 0) -> None:
def getProjectPath(self, parent: QWidget, path: str | Path | None = None,
allowZip: bool = False) -> Path | None:
"""Open the file dialog and select a novelWriter project file."""
label = (self.tr("novelWriter Project File or Zip")
label = (self.tr("novelWriter Project File or Zip File")
if allowZip else self.tr("novelWriter Project File"))
ext = f"{nwFiles.PROJ_FILE} *.zip" if allowZip else nwFiles.PROJ_FILE
ffilter = formatFileFilter([(label, ext), "*"])
selected, _ = QFileDialog.getOpenFileName(
parent, self.tr("Open Project"), str(path or ""), filter=";;".join(
[f"{label} ({ext})", "{0} (*)".format(self.tr("All Files"))]
)
parent, self.tr("Open Project"), str(path or ""), filter=ffilter
)
return Path(selected) if selected else None

Expand Down
11 changes: 5 additions & 6 deletions novelwriter/tools/dictionaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

from novelwriter import CONFIG, SHARED
from novelwriter.error import formatException
from novelwriter.common import openExternalPath, formatInt, getFileSize
from novelwriter.common import formatFileFilter, openExternalPath, formatInt, getFileSize

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -180,12 +180,11 @@ def closeEvent(self, event: QCloseEvent) -> None:
@pyqtSlot()
def _doBrowseHunspell(self):
"""Browse for a Free/Libre Office dictionary."""
extFilter = [
self.tr("Free or Libre Office extension ({0})").format("*.sox *.oxt"),
self.tr("All files ({0})").format("*"),
]
ffilter = formatFileFilter([
(self.tr("Free or Libre Office extension"), "*.sox *.oxt"), "*"
])
soxFile, _ = QFileDialog.getOpenFileName(
self, self.tr("Browse Files"), "", filter=";;".join(extFilter)
self, self.tr("Browse Files"), "", filter=ffilter
)
if soxFile:
path = Path(soxFile).absolute()
Expand Down
2 changes: 1 addition & 1 deletion novelwriter/tools/writingstats.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ def _saveData(self, dataFmt: int) -> bool:
# Generate the file name
savePath = CONFIG.lastPath() / f"sessionStats.{fileExt}"
savePath, _ = QFileDialog.getSaveFileName(
self, self.tr("Save Data As"), str(savePath), "%s (*.%s)" % (textFmt, fileExt)
self, self.tr("Save Data As"), str(savePath), f"{textFmt} (*.{fileExt})"
)
if not savePath:
return False
Expand Down
22 changes: 17 additions & 5 deletions tests/test_base/test_base_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@

from novelwriter.common import (
checkBool, checkFloat, checkInt, checkIntTuple, checkPath, checkString,
checkStringNone, checkUuid, formatInt, formatTime, formatTimeStamp,
formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass,
isItemLayout, isItemType, isTitleTag, jsonEncode, makeFileNameSafe, minmax,
numberToRoman, NWConfigParser, openExternalPath, readTextFile, simplified,
transferCase, xmlIndent, yesNo
checkStringNone, checkUuid, formatFileFilter, formatInt, formatTime,
formatTimeStamp, formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle,
isItemClass, isItemLayout, isItemType, isTitleTag, jsonEncode,
makeFileNameSafe, minmax, numberToRoman, NWConfigParser, openExternalPath,
readTextFile, simplified, transferCase, xmlIndent, yesNo
)


Expand Down Expand Up @@ -346,6 +346,18 @@ def testBaseCommon_formatVersion():
# END Test testBaseCommon_formatVersion


@pytest.mark.base
def testBaseCommon_formatFileFilter():
"""Test the formatFileFilter function."""
assert formatFileFilter(["*.txt"]) == "Text files (*.txt)"
assert formatFileFilter(["*.txt", "*"]) == "Text files (*.txt);;All files (*)"
assert formatFileFilter([("Stuff", "*.stuff"), "*.txt", "*"]) == (
"Stuff (*.stuff);;Text files (*.txt);;All files (*)"
)

# END Test testBaseCommon_formatFileFilter


@pytest.mark.base
def testBaseCommon_simplified():
"""Test the simplified function."""
Expand Down

0 comments on commit fb92c6c

Please sign in to comment.