diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index a420cd7d44..efa46fa7ae 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -135,32 +135,53 @@ auto_connect_to_folder = '' # metadata management is set to automatic. Collections on Sonys are named # depending upon whether the field is standard or custom. A collection derived # from a standard field is named for the value in that field. For example, if -# the standard 'series' column contains the name 'Darkover', then the series -# will be named 'Darkover'. A collection derived from a custom field will have -# the name of the field added to the value. For example, if a custom series +# the standard 'series' column contains the value 'Darkover', then the +# collection name is 'Darkover'. A collection derived from a custom field will +# have the name of the field added to the value. For example, if a custom series # column named 'My Series' contains the name 'Darkover', then the collection -# will be named 'Darkover (My Series)'. If two books have fields that generate -# the same collection name, then both books will be in that collection. This -# tweak lets you specify for a standard or custom field the value to be put -# inside the parentheses. You can use it to add a parenthetical description to a +# will by default be named 'Darkover (My Series)'. For purposes of this +# documentation, 'Darkover' is called the value and 'My Series' is called the +# category. If two books have fields that generate the same collection name, +# then both books will be in that collection. +# This set of tweaks lets you specify for a standard or custom field how +# the collections are to be named. You can use it to add a description to a # standard field, for example 'Foo (Tag)' instead of the 'Foo'. You can also use # it to force multiple fields to end up in the same collection. For example, you # could force the values in 'series', '#my_series_1', and '#my_series_2' to # appear in collections named 'some_value (Series)', thereby merging all of the -# fields into one set of collections. The syntax of this tweak is -# {'field_lookup_name':'name_to_use', 'lookup_name':'name', ...} -# Example 1: I want three series columns to be merged into one set of -# collections. If the column lookup names are 'series', '#series_1' and -# '#series_2', and if I want nothing in the parenthesis, then the value to use -# in the tweak value would be: -# sony_collection_renaming_rules={'series':'', '#series_1':'', '#series_2':''} -# Example 2: I want the word '(Series)' to appear on collections made from -# series, and the word '(Tag)' to appear on collections made from tags. Use: -# sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'} -# Example 3: I want 'series' and '#myseries' to be merged, and for the -# collection name to have '(Series)' appended. The renaming rule is: -# sony_collection_renaming_rules={'series':'Series', '#myseries':'Series'} +# fields into one set of collections. +# There are two related tweaks. The first determines the category name to use +# for a metadata field. The second is a template, used to determines how the +# value and category are combined to create the collection name. +# The syntax of the first tweak, sony_collection_renaming_rules, is: +# {'field_lookup_name':'category_name_to_use', 'lookup_name':'name', ...} +# The second tweak, sony_collection_name_template, is a template. It uses the +# same template language as plugboards and save templates. This tweak controls +# how the value and category are combined together to make the collection name. +# The only two fields available are {category} and {value}. The {value} field is +# never empty. The {category} field can be empty. The default is to put the +# value first, then the category enclosed in parentheses, it is isn't empty: +# '{value} {category:|(|)}' +# Examples: The first three examples assume that the second tweak +# has not been changed. +# 1: I want three series columns to be merged into one set of collections. The +# column lookup names are 'series', '#series_1' and '#series_2'. I want nothing +# in the parenthesis. The value to use in the tweak value would be: +# sony_collection_renaming_rules={'series':'', '#series_1':'', '#series_2':''} +# 2: I want the word '(Series)' to appear on collections made from series, and +# the word '(Tag)' to appear on collections made from tags. Use: +# sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'} +# 3: I want 'series' and '#myseries' to be merged, and for the collection name +# to have '(Series)' appended. The renaming rule is: +# sony_collection_renaming_rules={'series':'Series', '#myseries':'Series'} +# 4: Same as example 2, but instead of having the category name in parentheses +# and appended to the value, I want it prepended and separated by a colon, such +# as in Series: Darkover. I must change the template used to format the category name +# The resulting two tweaks are: +# sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'} +# sony_collection_name_template='{category:||: }{value}' sony_collection_renaming_rules={} +sony_collection_name_template='{value}{category:| (|)}' # Specify how sony collections are sorted. This tweak is only applicable if @@ -244,8 +265,10 @@ generate_cover_title_font = None generate_cover_foot_font = None -# Behavior of doubleclick on the books list. Choices: -# open_viewer, do_nothing, edit_cell. Default: open_viewer. +# Behavior of doubleclick on the books list. Choices: open_viewer, do_nothing, +# edit_cell, edit_metadata. Selecting edit_metadata has the side effect of +# disabling editing a field using a single click. +# Default: open_viewer. # Example: doubleclick_on_library_view = 'do_nothing' doubleclick_on_library_view = 'open_viewer' @@ -265,4 +288,4 @@ locale_for_sorting = '' # Set whether to use one or two columns for custom metadata when editing # metadata one book at a time. If True, then the fields are laid out using two # columns. If False, one column is used. -metadata_single_use_2_cols_for_custom_fields = True \ No newline at end of file +metadata_single_use_2_cols_for_custom_fields = True diff --git a/src/calibre/devices/usbms/books.py b/src/calibre/devices/usbms/books.py index ba005c4e6d..73afd770c1 100644 --- a/src/calibre/devices/usbms/books.py +++ b/src/calibre/devices/usbms/books.py @@ -14,6 +14,22 @@ from calibre.constants import preferred_encoding from calibre import isbytestring, force_unicode from calibre.utils.config import prefs, tweaks from calibre.utils.icu import strcmp +from calibre.utils.formatter import TemplateFormatter + +class SafeFormat(TemplateFormatter): + ''' + Provides a format function that substitutes '' for any missing value + ''' + + def get_value(self, key, args, kwargs): + try: + if key in kwargs: + return kwargs[key] + return key + except: + return key + +safe_formatter = SafeFormat() class Book(Metadata): def __init__(self, prefix, lpath, size=None, other=None): @@ -107,23 +123,25 @@ class CollectionsBookList(BookList): return sortattr return None - def compute_category_name(self, attr, category, field_meta): + def compute_category_name(self, field_key, field_value, field_meta): renames = tweaks['sony_collection_renaming_rules'] - attr_name = renames.get(attr, None) - if attr_name is None: + field_name = renames.get(field_key, None) + if field_name is None: if field_meta['is_custom']: - attr_name = '(%s)'%field_meta['name'] + field_name = field_meta['name'] else: - attr_name = '' - elif attr_name != '': - attr_name = '(%s)'%attr_name - cat_name = '%s %s'%(category, attr_name) + field_name = '' + cat_name = safe_formatter.safe_format( + fmt=tweaks['sony_collection_name_template'], + kwargs={'category':field_name, 'value':field_value}, + error_value='', book=None) return cat_name.strip() def get_collections(self, collection_attributes): from calibre.devices.usbms.driver import debug_print debug_print('Starting get_collections:', prefs['manage_device_metadata']) debug_print('Renaming rules:', tweaks['sony_collection_renaming_rules']) + debug_print('Formatting template:', tweaks['sony_collection_name_template']) debug_print('Sorting rules:', tweaks['sony_collection_sorting_rules']) # Complexity: we can use renaming rules only when using automatic diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py index dc691c4ffe..bde5cae128 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.py +++ b/src/calibre/gui2/dialogs/metadata_bulk.py @@ -414,6 +414,9 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.s_r_template.completer().setCaseSensitivity(Qt.CaseSensitive) self.s_r_search_mode_changed(self.search_mode.currentIndex()) + self.multiple_separator.setFixedWidth(30) + self.multiple_separator.setText(' ::: ') + self.multiple_separator.textChanged.connect(self.s_r_separator_changed) def s_r_get_field(self, mi, field): if field: @@ -451,19 +454,22 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): mi = self.db.get_metadata(self.ids[i], index_is_id=True) src = unicode(self.search_field.currentText()) t = self.s_r_get_field(mi, src) - w.setText(''.join(t[0:1])) + w.setText(unicode(self.multiple_separator.text()).join(t)) if self.search_mode.currentIndex() == 0: self.destination_field.setCurrentIndex(idx) else: + self.s_r_destination_field_changed(self.destination_field.currentText()) self.s_r_paint_results(None) def s_r_destination_field_changed(self, txt): txt = unicode(txt) + if not txt: + txt = unicode(self.search_field.currentText()) self.comma_separated.setEnabled(True) - if txt: - fm = self.db.metadata_for_field(txt) - if fm['is_multiple']: + if txt and txt in self.writable_fields: + self.destination_field_fm = self.db.metadata_for_field(txt) + if self.destination_field_fm['is_multiple']: self.comma_separated.setEnabled(False) self.comma_separated.setChecked(True) self.s_r_paint_results(None) @@ -493,6 +499,9 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.s_r_heading.setText('
'+self.main_heading + self.regexp_heading)
self.s_r_paint_results(None)
+ def s_r_separator_changed(self, txt):
+ self.s_r_search_field_changed(self.search_field.currentIndex())
+
def s_r_set_colors(self):
if self.s_r_error is not None:
col = 'rgb(255, 0, 0, 20%)'
@@ -592,8 +601,12 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
wr = getattr(self, 'book_%d_result'%(i+1))
try:
result = self.s_r_do_regexp(mi)
- t = self.s_r_do_destination(mi, result[0:1])
- t = self.s_r_replace_mode_separator().join(t)
+ t = self.s_r_do_destination(mi, result)
+ if len(result) > 1 and self.destination_field_fm is not None and \
+ self.destination_field_fm['is_multiple']:
+ t = unicode(self.multiple_separator.text()).join(t)
+ else:
+ t = self.s_r_replace_mode_separator().join(t)
wr.setText(t)
except Exception as e:
self.s_r_error = e
diff --git a/src/calibre/gui2/dialogs/metadata_bulk.ui b/src/calibre/gui2/dialogs/metadata_bulk.ui
index dca7abc82c..d945909f96 100644
--- a/src/calibre/gui2/dialogs/metadata_bulk.ui
+++ b/src/calibre/gui2/dialogs/metadata_bulk.ui
@@ -478,7 +478,7 @@ Future conversion of these books will use the default settings.