Add replacement settings
This commit is contained in:
parent
82d737407f
commit
ed1df400d8
@ -502,7 +502,11 @@ def process_file_cli(
|
||||
elif ca.is_rar():
|
||||
new_ext = ".cbr"
|
||||
|
||||
renamer = FileRenamer(md, platform="universal" if options[filename]["rename_strict"] else "auto")
|
||||
renamer = FileRenamer(
|
||||
md,
|
||||
platform="universal" if options[filename]["rename_strict"] else "auto",
|
||||
replacements=options["rename"]["replacements"],
|
||||
)
|
||||
renamer.set_template(options[filename]["rename_template"])
|
||||
renamer.set_issue_zero_padding(options[filename]["rename_issue_number_padding"])
|
||||
renamer.set_smart_cleanup(options[filename]["rename_use_smart_string_cleanup"])
|
||||
|
29
comictaggerlib/defaults.py
Normal file
29
comictaggerlib/defaults.py
Normal file
@ -0,0 +1,29 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import NamedTuple
|
||||
|
||||
|
||||
class Replacement(NamedTuple):
|
||||
find: str
|
||||
replce: str
|
||||
strict_only: bool
|
||||
|
||||
|
||||
class Replacements(NamedTuple):
|
||||
literal_text: list[Replacement]
|
||||
format_value: list[Replacement]
|
||||
|
||||
|
||||
DEFAULT_REPLACEMENTS = Replacements(
|
||||
literal_text=[
|
||||
Replacement(": ", " - ", True),
|
||||
Replacement(":", "-", True),
|
||||
],
|
||||
format_value=[
|
||||
Replacement(": ", " - ", True),
|
||||
Replacement(":", "-", True),
|
||||
Replacement("/", "-", False),
|
||||
Replacement("//", "--", False),
|
||||
Replacement("\\", "-", True),
|
||||
],
|
||||
)
|
@ -20,42 +20,18 @@ import logging
|
||||
import os
|
||||
import pathlib
|
||||
import string
|
||||
from typing import Any, NamedTuple, cast
|
||||
from typing import Any, cast
|
||||
|
||||
from pathvalidate import Platform, normalize_platform, sanitize_filename
|
||||
|
||||
from comicapi.comicarchive import ComicArchive
|
||||
from comicapi.genericmetadata import GenericMetadata
|
||||
from comicapi.issuestring import IssueString
|
||||
from comictaggerlib.defaults import DEFAULT_REPLACEMENTS, Replacement, Replacements
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Replacement(NamedTuple):
|
||||
find: str
|
||||
replce: str
|
||||
strict_only: bool
|
||||
|
||||
|
||||
class Replacements(NamedTuple):
|
||||
literal_text: list[Replacement]
|
||||
format_value: list[Replacement]
|
||||
|
||||
|
||||
REPLACEMENTS = Replacements(
|
||||
literal_text=[
|
||||
Replacement(": ", " - ", True),
|
||||
Replacement(":", "-", True),
|
||||
],
|
||||
format_value=[
|
||||
Replacement(": ", " - ", True),
|
||||
Replacement(":", "-", True),
|
||||
Replacement("/", "-", False),
|
||||
Replacement("\\", "-", True),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def get_rename_dir(ca: ComicArchive, rename_dir: str | pathlib.Path | None) -> pathlib.Path:
|
||||
folder = ca.path.parent.absolute()
|
||||
if rename_dir is not None:
|
||||
@ -67,7 +43,7 @@ def get_rename_dir(ca: ComicArchive, rename_dir: str | pathlib.Path | None) -> p
|
||||
|
||||
class MetadataFormatter(string.Formatter):
|
||||
def __init__(
|
||||
self, smart_cleanup: bool = False, platform: str = "auto", replacements: Replacements = REPLACEMENTS
|
||||
self, smart_cleanup: bool = False, platform: str = "auto", replacements: Replacements = DEFAULT_REPLACEMENTS
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.smart_cleanup = smart_cleanup
|
||||
@ -200,13 +176,19 @@ class MetadataFormatter(string.Formatter):
|
||||
|
||||
|
||||
class FileRenamer:
|
||||
def __init__(self, metadata: GenericMetadata | None, platform: str = "auto") -> None:
|
||||
def __init__(
|
||||
self,
|
||||
metadata: GenericMetadata | None,
|
||||
platform: str = "auto",
|
||||
replacements: Replacements = DEFAULT_REPLACEMENTS,
|
||||
) -> None:
|
||||
self.template = "{publisher}/{series}/{series} v{volume} #{issue} (of {issue_count}) ({year})"
|
||||
self.smart_cleanup = True
|
||||
self.issue_zero_padding = 3
|
||||
self.metadata = metadata or GenericMetadata()
|
||||
self.move = False
|
||||
self.platform = platform
|
||||
self.replacements = replacements
|
||||
|
||||
def set_metadata(self, metadata: GenericMetadata) -> None:
|
||||
self.metadata = metadata
|
||||
@ -234,7 +216,7 @@ class FileRenamer:
|
||||
|
||||
new_name = ""
|
||||
|
||||
fmt = MetadataFormatter(self.smart_cleanup, platform=self.platform)
|
||||
fmt = MetadataFormatter(self.smart_cleanup, platform=self.platform, replacements=self.replacements)
|
||||
md_dict = vars(md)
|
||||
for role in ["writer", "penciller", "inker", "colorist", "letterer", "cover artist", "editor"]:
|
||||
md_dict[role] = md.get_primary_credit(role)
|
||||
|
@ -62,7 +62,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
|
||||
self.btnSettings.clicked.connect(self.modify_settings)
|
||||
platform = "universal" if self.options["filename"]["rename_strict"] else "auto"
|
||||
self.renamer = FileRenamer(None, platform=platform)
|
||||
self.renamer = FileRenamer(None, platform=platform, replacements=self.options["rename"]["replacements"])
|
||||
|
||||
self.do_preview()
|
||||
|
||||
@ -70,6 +70,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
self.renamer.set_template(self.options["filename"]["rename_template"])
|
||||
self.renamer.set_issue_zero_padding(self.options["filename"]["rename_issue_number_padding"])
|
||||
self.renamer.set_smart_cleanup(self.options["filename"]["rename_use_smart_string_cleanup"])
|
||||
self.renamer.replacements = self.options["rename"]["replacements"]
|
||||
|
||||
new_ext = ca.path.suffix # default
|
||||
if self.options["filename"]["rename_set_extension_based_on_archive"]:
|
||||
|
@ -2,10 +2,11 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import uuid
|
||||
from collections.abc import Sequence
|
||||
from typing import Any, Callable
|
||||
from typing import Any
|
||||
|
||||
from comictaggerlib.defaults import DEFAULT_REPLACEMENTS, Replacement, Replacements
|
||||
from comictaggerlib.settings.manager import Manager
|
||||
from comictaggerlib.settings.types import AppendAction
|
||||
|
||||
|
||||
def general(parser: Manager) -> None:
|
||||
@ -38,75 +39,10 @@ def identifier(parser: Manager) -> None:
|
||||
parser.add_setting(
|
||||
"--publisher-filter",
|
||||
default=["Panini Comics", "Abril", "Planeta DeAgostini", "Editorial Televisa", "Dino Comics"],
|
||||
action=_AppendAction,
|
||||
action=AppendAction,
|
||||
)
|
||||
|
||||
|
||||
def _copy_items(items: Sequence[Any] | None) -> Sequence[Any]:
|
||||
if items is None:
|
||||
return []
|
||||
# The copy module is used only in the 'append' and 'append_const'
|
||||
# actions, and it is needed only when the default value isn't a list.
|
||||
# Delay its import for speeding up the common case.
|
||||
if type(items) is list:
|
||||
return items[:]
|
||||
import copy
|
||||
|
||||
return copy.copy(items)
|
||||
|
||||
|
||||
class _AppendAction(argparse.Action):
|
||||
def __init__(
|
||||
self,
|
||||
option_strings: list[str],
|
||||
dest: str,
|
||||
nargs: str | None = None,
|
||||
const: Any = None,
|
||||
default: Any = None,
|
||||
type: Callable[[str], Any] | None = None, # noqa: A002
|
||||
choices: list[Any] | None = None,
|
||||
required: bool = False,
|
||||
help: str | None = None, # noqa: A002
|
||||
metavar: str | None = None,
|
||||
):
|
||||
self.called = False
|
||||
if nargs == 0:
|
||||
raise ValueError(
|
||||
"nargs for append actions must be != 0; if arg "
|
||||
"strings are not supplying the value to append, "
|
||||
"the append const action may be more appropriate"
|
||||
)
|
||||
if const is not None and nargs != argparse.OPTIONAL:
|
||||
raise ValueError("nargs must be %r to supply const" % argparse.OPTIONAL)
|
||||
super().__init__(
|
||||
option_strings=option_strings,
|
||||
dest=dest,
|
||||
nargs=nargs,
|
||||
const=const,
|
||||
default=default,
|
||||
type=type,
|
||||
choices=choices,
|
||||
required=required,
|
||||
help=help,
|
||||
metavar=metavar,
|
||||
)
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
parser: argparse.ArgumentParser,
|
||||
namespace: argparse.Namespace,
|
||||
values: str | Sequence[Any] | None,
|
||||
option_string: str | None = None,
|
||||
) -> None:
|
||||
if values:
|
||||
if not self.called:
|
||||
setattr(namespace, self.dest, [])
|
||||
items = getattr(namespace, self.dest, None)
|
||||
items = _copy_items(items)
|
||||
items.append(values) # type: ignore
|
||||
setattr(namespace, self.dest, items)
|
||||
|
||||
|
||||
def dialog(parser: Manager) -> None:
|
||||
# Show/ask dialog flags
|
||||
parser.add_setting("ask_about_cbi_in_rar", default=True, cmdline=False)
|
||||
@ -140,12 +76,10 @@ def comicvine(parser: Manager) -> None:
|
||||
parser.add_setting("--remove-html-tables", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting(
|
||||
"--cv-api-key",
|
||||
default="",
|
||||
help="Use the given Comic Vine API Key (persisted in settings).",
|
||||
)
|
||||
parser.add_setting(
|
||||
"--cv-url",
|
||||
default="",
|
||||
help="Use the given Comic Vine URL (persisted in settings).",
|
||||
)
|
||||
parser.add_setting(
|
||||
@ -184,6 +118,11 @@ def rename(parser: Manager) -> None:
|
||||
parser.add_setting("--dir", default="")
|
||||
parser.add_setting("--move-to-dir", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting("--strict", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting(
|
||||
"replacements",
|
||||
default=DEFAULT_REPLACEMENTS,
|
||||
cmdline=False,
|
||||
)
|
||||
|
||||
|
||||
def autotag(parser: Manager) -> None:
|
||||
@ -214,6 +153,10 @@ def validate_settings(options: dict[str, dict[str, Any]], parser: Manager) -> di
|
||||
options["identifier"]["publisher_filter"] = [
|
||||
x.strip() for x in options["identifier"]["publisher_filter"] if x.strip()
|
||||
]
|
||||
options["rename"]["replacements"] = Replacements(
|
||||
[Replacement(x[0], x[1], x[2]) for x in options["rename"]["replacements"][0]],
|
||||
[Replacement(x[0], x[1], x[2]) for x in options["rename"]["replacements"][1]],
|
||||
)
|
||||
return options
|
||||
|
||||
|
||||
|
@ -2,7 +2,8 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
from typing import Any
|
||||
from collections.abc import Sequence
|
||||
from typing import Any, Callable
|
||||
|
||||
from appdirs import AppDirs
|
||||
|
||||
@ -72,6 +73,71 @@ def metadata_type(types: str) -> list[int]:
|
||||
return result
|
||||
|
||||
|
||||
def _copy_items(items: Sequence[Any] | None) -> Sequence[Any]:
|
||||
if items is None:
|
||||
return []
|
||||
# The copy module is used only in the 'append' and 'append_const'
|
||||
# actions, and it is needed only when the default value isn't a list.
|
||||
# Delay its import for speeding up the common case.
|
||||
if type(items) is list:
|
||||
return items[:]
|
||||
import copy
|
||||
|
||||
return copy.copy(items)
|
||||
|
||||
|
||||
class AppendAction(argparse.Action):
|
||||
def __init__(
|
||||
self,
|
||||
option_strings: list[str],
|
||||
dest: str,
|
||||
nargs: str | None = None,
|
||||
const: Any = None,
|
||||
default: Any = None,
|
||||
type: Callable[[str], Any] | None = None, # noqa: A002
|
||||
choices: list[Any] | None = None,
|
||||
required: bool = False,
|
||||
help: str | None = None, # noqa: A002
|
||||
metavar: str | None = None,
|
||||
):
|
||||
self.called = False
|
||||
if nargs == 0:
|
||||
raise ValueError(
|
||||
"nargs for append actions must be != 0; if arg "
|
||||
"strings are not supplying the value to append, "
|
||||
"the append const action may be more appropriate"
|
||||
)
|
||||
if const is not None and nargs != argparse.OPTIONAL:
|
||||
raise ValueError("nargs must be %r to supply const" % argparse.OPTIONAL)
|
||||
super().__init__(
|
||||
option_strings=option_strings,
|
||||
dest=dest,
|
||||
nargs=nargs,
|
||||
const=const,
|
||||
default=default,
|
||||
type=type,
|
||||
choices=choices,
|
||||
required=required,
|
||||
help=help,
|
||||
metavar=metavar,
|
||||
)
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
parser: argparse.ArgumentParser,
|
||||
namespace: argparse.Namespace,
|
||||
values: str | Sequence[Any] | None,
|
||||
option_string: str | None = None,
|
||||
) -> None:
|
||||
if values:
|
||||
if not self.called:
|
||||
setattr(namespace, self.dest, [])
|
||||
items = getattr(namespace, self.dest, None)
|
||||
items = _copy_items(items)
|
||||
items.append(values) # type: ignore
|
||||
setattr(namespace, self.dest, items)
|
||||
|
||||
|
||||
def parse_metadata_from_string(mdstr: str) -> GenericMetadata:
|
||||
"""The metadata string is a comma separated list of name-value pairs
|
||||
The names match the attributes of the internal metadata struct (for now)
|
||||
|
@ -20,6 +20,7 @@ import logging
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
from typing import Any
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets, uic
|
||||
|
||||
@ -27,7 +28,7 @@ from comicapi import utils
|
||||
from comicapi.genericmetadata import md_test
|
||||
from comictaggerlib import settings
|
||||
from comictaggerlib.ctversion import version
|
||||
from comictaggerlib.filerenamer import FileRenamer
|
||||
from comictaggerlib.filerenamer import FileRenamer, Replacement, Replacements
|
||||
from comictaggerlib.imagefetcher import ImageFetcher
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictalker.comiccacher import ComicCacher
|
||||
@ -190,23 +191,64 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.btnResetSettings.clicked.connect(self.reset_settings)
|
||||
self.btnTestKey.clicked.connect(self.test_api_key)
|
||||
self.btnTemplateHelp.clicked.connect(self.show_template_help)
|
||||
self.leRenameTemplate.textEdited.connect(self._rename_test)
|
||||
self.cbxMoveFiles.clicked.connect(self.rename_test)
|
||||
self.cbxMoveFiles.clicked.connect(self.dir_test)
|
||||
self.cbxRenameStrict.clicked.connect(self.rename_test)
|
||||
self.leDirectory.textEdited.connect(self.dir_test)
|
||||
self.cbxComplicatedParser.clicked.connect(self.switch_parser)
|
||||
|
||||
def rename_test(self) -> None:
|
||||
self.btnAddLiteralReplacement.clicked.connect(self.addLiteralReplacement)
|
||||
self.btnAddValueReplacement.clicked.connect(self.addValueReplacement)
|
||||
self.btnRemoveLiteralReplacement.clicked.connect(self.removeLiteralReplacement)
|
||||
self.btnRemoveValueReplacement.clicked.connect(self.removeValueReplacement)
|
||||
|
||||
self.leRenameTemplate.textEdited.connect(self.rename_test)
|
||||
self.cbxMoveFiles.clicked.connect(self.rename_test)
|
||||
self.cbxRenameStrict.clicked.connect(self.rename_test)
|
||||
self.cbxSmartCleanup.clicked.connect(self.rename_test)
|
||||
self.cbxChangeExtension.clicked.connect(self.rename_test)
|
||||
self.leIssueNumPadding.textEdited.connect(self.rename_test)
|
||||
self.twLiteralReplacements.cellChanged.connect(self.rename_test)
|
||||
self.twValueReplacements.cellChanged.connect(self.rename_test)
|
||||
|
||||
def addLiteralReplacement(self) -> None:
|
||||
self.insertRow(self.twLiteralReplacements, self.twLiteralReplacements.rowCount(), Replacement("", "", False))
|
||||
|
||||
def addValueReplacement(self) -> None:
|
||||
self.insertRow(self.twValueReplacements, self.twValueReplacements.rowCount(), Replacement("", "", False))
|
||||
|
||||
def removeLiteralReplacement(self) -> None:
|
||||
if self.twLiteralReplacements.currentRow() >= 0:
|
||||
self.twLiteralReplacements.removeRow(self.twLiteralReplacements.currentRow())
|
||||
|
||||
def removeValueReplacement(self) -> None:
|
||||
if self.twValueReplacements.currentRow() >= 0:
|
||||
self.twValueReplacements.removeRow(self.twValueReplacements.currentRow())
|
||||
|
||||
def insertRow(self, table: QtWidgets.QTableWidget, row: int, replacement: Replacement) -> None:
|
||||
find, replace, strict_only = replacement
|
||||
table.insertRow(row)
|
||||
table.setItem(row, 0, QtWidgets.QTableWidgetItem(find))
|
||||
table.setItem(row, 1, QtWidgets.QTableWidgetItem(replace))
|
||||
tmp = QtWidgets.QTableWidgetItem()
|
||||
if strict_only:
|
||||
tmp.setCheckState(QtCore.Qt.Checked)
|
||||
else:
|
||||
tmp.setCheckState(QtCore.Qt.Unchecked)
|
||||
table.setItem(row, 2, tmp)
|
||||
|
||||
def rename_test(self, *args: Any, **kwargs: Any) -> None:
|
||||
self._rename_test(self.leRenameTemplate.text())
|
||||
|
||||
def dir_test(self) -> None:
|
||||
self.lblDir.setText(
|
||||
str(pathlib.Path(self.leDirectory.text().strip()).absolute()) if self.cbxMoveFiles.isChecked() else ""
|
||||
str(pathlib.Path(self.leDirectory.text().strip()).resolve()) if self.cbxMoveFiles.isChecked() else ""
|
||||
)
|
||||
|
||||
def _rename_test(self, template: str) -> None:
|
||||
fr = FileRenamer(md_test, platform="universal" if self.cbxRenameStrict.isChecked() else "auto")
|
||||
fr = FileRenamer(
|
||||
md_test,
|
||||
platform="universal" if self.cbxRenameStrict.isChecked() else "auto",
|
||||
replacements=self.get_replacemnts(),
|
||||
)
|
||||
fr.move = self.cbxMoveFiles.isChecked()
|
||||
fr.set_template(template)
|
||||
fr.set_issue_zero_padding(int(self.leIssueNumPadding.text()))
|
||||
@ -271,6 +313,38 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.leDirectory.setText(self.options["rename"]["dir"])
|
||||
self.cbxRenameStrict.setChecked(self.options["rename"]["strict"])
|
||||
|
||||
for table, replacments in zip(
|
||||
(self.twLiteralReplacements, self.twValueReplacements), self.options["rename"]["replacements"]
|
||||
):
|
||||
table.clearContents()
|
||||
for i in reversed(range(table.rowCount())):
|
||||
table.removeRow(i)
|
||||
for row, replacement in enumerate(replacments):
|
||||
self.insertRow(table, row, replacement)
|
||||
|
||||
def get_replacemnts(self) -> Replacements:
|
||||
literal_replacements = []
|
||||
value_replacements = []
|
||||
for row in range(self.twLiteralReplacements.rowCount()):
|
||||
if self.twLiteralReplacements.item(row, 0).text():
|
||||
literal_replacements.append(
|
||||
Replacement(
|
||||
self.twLiteralReplacements.item(row, 0).text(),
|
||||
self.twLiteralReplacements.item(row, 1).text(),
|
||||
self.twLiteralReplacements.item(row, 2).checkState() == QtCore.Qt.Checked,
|
||||
)
|
||||
)
|
||||
for row in range(self.twValueReplacements.rowCount()):
|
||||
if self.twValueReplacements.item(row, 0).text():
|
||||
value_replacements.append(
|
||||
Replacement(
|
||||
self.twValueReplacements.item(row, 0).text(),
|
||||
self.twValueReplacements.item(row, 1).text(),
|
||||
self.twValueReplacements.item(row, 2).checkState() == QtCore.Qt.Checked,
|
||||
)
|
||||
)
|
||||
return Replacements(literal_replacements, value_replacements)
|
||||
|
||||
def accept(self) -> None:
|
||||
self.rename_test()
|
||||
if self.rename_error is not None:
|
||||
@ -362,6 +436,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.options["rename"]["dir"] = self.leDirectory.text()
|
||||
|
||||
self.options["rename"]["strict"] = self.cbxRenameStrict.isChecked()
|
||||
self.options["rename"]["replacements"] = self.get_replacemnts()
|
||||
|
||||
settings.Manager().save_file(self.options, self.options["runtime"]["config"].user_config_dir / "settings.json")
|
||||
self.parent().options = self.options
|
||||
@ -402,9 +477,9 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
|
||||
dialog.setDirectory(os.path.dirname(str(control.text())))
|
||||
if name == "RAR":
|
||||
dialog.setWindowTitle("Find " + name + " program")
|
||||
dialog.setWindowTitle(f"Find {name} program")
|
||||
else:
|
||||
dialog.setWindowTitle("Find " + name + " library")
|
||||
dialog.setWindowTitle(f"Find {name} library")
|
||||
|
||||
if dialog.exec():
|
||||
file_list = dialog.selectedFiles()
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>702</width>
|
||||
<height>488</height>
|
||||
<height>513</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -616,7 +616,21 @@
|
||||
<string>Rename</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="btnAddValueReplacement">
|
||||
<property name="text">
|
||||
<string>Add Replacement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="btnRemoveLiteralReplacement">
|
||||
<property name="text">
|
||||
<string>Remove Replacement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
@ -717,8 +731,7 @@
|
||||
<item row="8" column="0">
|
||||
<widget class="QCheckBox" name="cbxRenameStrict">
|
||||
<property name="toolTip">
|
||||
<string>If checked will ensure reserved characters and filenames are removed for all Operating Systems.
|
||||
By default only removes restricted characters and filenames for the current Operating System.</string>
|
||||
<string>If checked will ensure reserved characters and filenames are removed for all Operating Systems.<br/>By default only removes restricted characters and filenames for the current Operating System.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Strict renaming</string>
|
||||
@ -730,6 +743,118 @@ By default only removes restricted characters and filenames for the current Oper
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="btnAddLiteralReplacement">
|
||||
<property name="text">
|
||||
<string>Add Replacement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="btnRemoveValueReplacement">
|
||||
<property name="text">
|
||||
<string>Remove Replacement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QTableWidget" name="twValueReplacements">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monaco</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Find</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Replacement</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Strict Only</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="twLiteralReplacements">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monaco</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Find</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Replacement</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Strict Only</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QLabel" name="lblValueReplacements">
|
||||
<property name="text">
|
||||
<string>Value Text Replacements</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lblLiteralReplacements">
|
||||
<property name="text">
|
||||
<string>Literal Text Replacements</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tRARTools">
|
||||
|
Loading…
Reference in New Issue
Block a user