mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
A new 'authors type' custom column
This commit is contained in:
commit
ca2d9875bd
@ -575,6 +575,9 @@ class Metadata(object):
|
|||||||
orig_res = res
|
orig_res = res
|
||||||
datatype = cmeta['datatype']
|
datatype = cmeta['datatype']
|
||||||
if datatype == 'text' and cmeta['is_multiple']:
|
if datatype == 'text' and cmeta['is_multiple']:
|
||||||
|
if cmeta['display'].get('is_names', False):
|
||||||
|
res = u' & '.join(res)
|
||||||
|
else:
|
||||||
res = u', '.join(sorted(res, key=sort_key))
|
res = u', '.join(sorted(res, key=sort_key))
|
||||||
elif datatype == 'series' and series_with_index:
|
elif datatype == 'series' and series_with_index:
|
||||||
if self.get_extra(key) is not None:
|
if self.get_extra(key) is not None:
|
||||||
|
@ -226,10 +226,18 @@ class Comments(Base):
|
|||||||
class Text(Base):
|
class Text(Base):
|
||||||
|
|
||||||
def setup_ui(self, parent):
|
def setup_ui(self, parent):
|
||||||
|
if self.col_metadata['display'].get('is_names', False):
|
||||||
|
self.sep = u' & '
|
||||||
|
else:
|
||||||
|
self.sep = u', '
|
||||||
values = self.all_values = list(self.db.all_custom(num=self.col_id))
|
values = self.all_values = list(self.db.all_custom(num=self.col_id))
|
||||||
values.sort(key=sort_key)
|
values.sort(key=sort_key)
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
w = MultiCompleteLineEdit(parent)
|
w = MultiCompleteLineEdit(parent)
|
||||||
|
w.set_separator(self.sep.strip())
|
||||||
|
if self.sep == u' & ':
|
||||||
|
w.set_space_before_sep(True)
|
||||||
|
w.set_add_separator(tweaks['authors_completer_append_separator'])
|
||||||
w.update_items_cache(values)
|
w.update_items_cache(values)
|
||||||
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
w.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||||
else:
|
else:
|
||||||
@ -261,12 +269,12 @@ class Text(Base):
|
|||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
if not val:
|
if not val:
|
||||||
val = []
|
val = []
|
||||||
self.widgets[1].setText(u', '.join(val))
|
self.widgets[1].setText(self.sep.join(val))
|
||||||
|
|
||||||
def getter(self):
|
def getter(self):
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
val = unicode(self.widgets[1].text()).strip()
|
val = unicode(self.widgets[1].text()).strip()
|
||||||
ans = [x.strip() for x in val.split(',') if x.strip()]
|
ans = [x.strip() for x in val.split(self.sep.strip()) if x.strip()]
|
||||||
if not ans:
|
if not ans:
|
||||||
ans = None
|
ans = None
|
||||||
return ans
|
return ans
|
||||||
@ -847,13 +855,20 @@ class BulkText(BulkBase):
|
|||||||
self.main_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
self.main_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
|
||||||
self.adding_widget = self.main_widget
|
self.adding_widget = self.main_widget
|
||||||
|
|
||||||
|
if not self.col_metadata['display'].get('is_names', False):
|
||||||
w = RemoveTags(parent, values)
|
w = RemoveTags(parent, values)
|
||||||
self.widgets.append(QLabel('&'+self.col_metadata['name']+': ' +
|
self.widgets.append(QLabel('&'+self.col_metadata['name']+': ' +
|
||||||
_('tags to remove'), parent))
|
_('tags to remove'), parent))
|
||||||
self.widgets.append(w)
|
self.widgets.append(w)
|
||||||
self.removing_widget = w
|
self.removing_widget = w
|
||||||
|
self.main_widget.set_separator(',')
|
||||||
w.tags_box.textChanged.connect(self.a_c_checkbox_changed)
|
w.tags_box.textChanged.connect(self.a_c_checkbox_changed)
|
||||||
w.checkbox.stateChanged.connect(self.a_c_checkbox_changed)
|
w.checkbox.stateChanged.connect(self.a_c_checkbox_changed)
|
||||||
|
else:
|
||||||
|
self.main_widget.set_separator('&')
|
||||||
|
self.main_widget.set_space_before_sep(True)
|
||||||
|
self.main_widget.set_add_separator(
|
||||||
|
tweaks['authors_completer_append_separator'])
|
||||||
else:
|
else:
|
||||||
self.make_widgets(parent, MultiCompleteComboBox)
|
self.make_widgets(parent, MultiCompleteComboBox)
|
||||||
self.main_widget.set_separator(None)
|
self.main_widget.set_separator(None)
|
||||||
@ -882,6 +897,11 @@ class BulkText(BulkBase):
|
|||||||
if not self.a_c_checkbox.isChecked():
|
if not self.a_c_checkbox.isChecked():
|
||||||
return
|
return
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
|
if self.col_metadata['display'].get('is_names', False):
|
||||||
|
val = self.gui_val
|
||||||
|
add = [v.strip() for v in val.split('&') if v.strip()]
|
||||||
|
self.db.set_custom_bulk(book_ids, add, num=self.col_id)
|
||||||
|
else:
|
||||||
remove_all, adding, rtext = self.gui_val
|
remove_all, adding, rtext = self.gui_val
|
||||||
remove = set()
|
remove = set()
|
||||||
if remove_all:
|
if remove_all:
|
||||||
@ -895,8 +915,8 @@ class BulkText(BulkBase):
|
|||||||
add = set([v.strip() for v in txt.split(',')])
|
add = set([v.strip() for v in txt.split(',')])
|
||||||
else:
|
else:
|
||||||
add = set()
|
add = set()
|
||||||
self.db.set_custom_bulk_multiple(book_ids, add=add, remove=remove,
|
self.db.set_custom_bulk_multiple(book_ids, add=add,
|
||||||
num=self.col_id)
|
remove=remove, num=self.col_id)
|
||||||
else:
|
else:
|
||||||
val = self.gui_val
|
val = self.gui_val
|
||||||
val = self.normalize_ui_val(val)
|
val = self.normalize_ui_val(val)
|
||||||
@ -905,10 +925,11 @@ class BulkText(BulkBase):
|
|||||||
|
|
||||||
def getter(self):
|
def getter(self):
|
||||||
if self.col_metadata['is_multiple']:
|
if self.col_metadata['is_multiple']:
|
||||||
|
if not self.col_metadata['display'].get('is_names', False):
|
||||||
return self.removing_widget.checkbox.isChecked(), \
|
return self.removing_widget.checkbox.isChecked(), \
|
||||||
unicode(self.adding_widget.text()), \
|
unicode(self.adding_widget.text()), \
|
||||||
unicode(self.removing_widget.tags_box.text())
|
unicode(self.removing_widget.tags_box.text())
|
||||||
|
return unicode(self.adding_widget.text())
|
||||||
val = unicode(self.main_widget.currentText()).strip()
|
val = unicode(self.main_widget.currentText()).strip()
|
||||||
if not val:
|
if not val:
|
||||||
val = None
|
val = None
|
||||||
|
@ -653,7 +653,10 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
|
|
||||||
if self.destination_field_fm['is_multiple']:
|
if self.destination_field_fm['is_multiple']:
|
||||||
if self.comma_separated.isChecked():
|
if self.comma_separated.isChecked():
|
||||||
if dest == 'authors':
|
if dest == 'authors' or \
|
||||||
|
(self.destination_field_fm['is_custom'] and
|
||||||
|
self.destination_field_fm['datatype'] == 'text' and
|
||||||
|
self.destination_field_fm['display'].get('is_names', False)):
|
||||||
splitter = ' & '
|
splitter = ' & '
|
||||||
else:
|
else:
|
||||||
splitter = ','
|
splitter = ','
|
||||||
|
@ -640,18 +640,18 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
return self.bool_yes_icon
|
return self.bool_yes_icon
|
||||||
return self.bool_blank_icon
|
return self.bool_blank_icon
|
||||||
|
|
||||||
def text_type(r, mult=False, idx=-1):
|
def text_type(r, mult=None, idx=-1):
|
||||||
text = self.db.data[r][idx]
|
text = self.db.data[r][idx]
|
||||||
if text and mult:
|
if text and mult is not None:
|
||||||
return QVariant(', '.join(sorted(text.split('|'),key=sort_key)))
|
if mult:
|
||||||
|
return QVariant(u' & '.join(text.split('|')))
|
||||||
|
return QVariant(u', '.join(sorted(text.split('|'),key=sort_key)))
|
||||||
return QVariant(text)
|
return QVariant(text)
|
||||||
|
|
||||||
def decorated_text_type(r, mult=False, idx=-1):
|
def decorated_text_type(r, idx=-1):
|
||||||
text = self.db.data[r][idx]
|
text = self.db.data[r][idx]
|
||||||
if force_to_bool(text) is not None:
|
if force_to_bool(text) is not None:
|
||||||
return None
|
return None
|
||||||
if text and mult:
|
|
||||||
return QVariant(', '.join(sorted(text.split('|'),key=sort_key)))
|
|
||||||
return QVariant(text)
|
return QVariant(text)
|
||||||
|
|
||||||
def number_type(r, idx=-1):
|
def number_type(r, idx=-1):
|
||||||
@ -659,7 +659,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
|
|
||||||
self.dc = {
|
self.dc = {
|
||||||
'title' : functools.partial(text_type,
|
'title' : functools.partial(text_type,
|
||||||
idx=self.db.field_metadata['title']['rec_index'], mult=False),
|
idx=self.db.field_metadata['title']['rec_index'], mult=None),
|
||||||
'authors' : functools.partial(authors,
|
'authors' : functools.partial(authors,
|
||||||
idx=self.db.field_metadata['authors']['rec_index']),
|
idx=self.db.field_metadata['authors']['rec_index']),
|
||||||
'size' : functools.partial(size,
|
'size' : functools.partial(size,
|
||||||
@ -671,14 +671,14 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
'rating' : functools.partial(rating_type,
|
'rating' : functools.partial(rating_type,
|
||||||
idx=self.db.field_metadata['rating']['rec_index']),
|
idx=self.db.field_metadata['rating']['rec_index']),
|
||||||
'publisher': functools.partial(text_type,
|
'publisher': functools.partial(text_type,
|
||||||
idx=self.db.field_metadata['publisher']['rec_index'], mult=False),
|
idx=self.db.field_metadata['publisher']['rec_index'], mult=None),
|
||||||
'tags' : functools.partial(tags,
|
'tags' : functools.partial(tags,
|
||||||
idx=self.db.field_metadata['tags']['rec_index']),
|
idx=self.db.field_metadata['tags']['rec_index']),
|
||||||
'series' : functools.partial(series_type,
|
'series' : functools.partial(series_type,
|
||||||
idx=self.db.field_metadata['series']['rec_index'],
|
idx=self.db.field_metadata['series']['rec_index'],
|
||||||
siix=self.db.field_metadata['series_index']['rec_index']),
|
siix=self.db.field_metadata['series_index']['rec_index']),
|
||||||
'ondevice' : functools.partial(text_type,
|
'ondevice' : functools.partial(text_type,
|
||||||
idx=self.db.field_metadata['ondevice']['rec_index'], mult=False),
|
idx=self.db.field_metadata['ondevice']['rec_index'], mult=None),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dc_decorator = {
|
self.dc_decorator = {
|
||||||
@ -692,11 +692,12 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
datatype = self.custom_columns[col]['datatype']
|
datatype = self.custom_columns[col]['datatype']
|
||||||
if datatype in ('text', 'comments', 'composite', 'enumeration'):
|
if datatype in ('text', 'comments', 'composite', 'enumeration'):
|
||||||
mult=self.custom_columns[col]['is_multiple']
|
mult=self.custom_columns[col]['is_multiple']
|
||||||
|
if mult is not None:
|
||||||
|
mult = self.custom_columns[col]['display'].get('is_names', False)
|
||||||
self.dc[col] = functools.partial(text_type, idx=idx, mult=mult)
|
self.dc[col] = functools.partial(text_type, idx=idx, mult=mult)
|
||||||
if datatype in ['text', 'composite', 'enumeration'] and not mult:
|
if datatype in ['text', 'composite', 'enumeration'] and not mult:
|
||||||
if self.custom_columns[col]['display'].get('use_decorations', False):
|
if self.custom_columns[col]['display'].get('use_decorations', False):
|
||||||
self.dc[col] = functools.partial(decorated_text_type,
|
self.dc[col] = functools.partial(decorated_text_type, idx=idx)
|
||||||
idx=idx, mult=mult)
|
|
||||||
self.dc_decorator[col] = functools.partial(
|
self.dc_decorator[col] = functools.partial(
|
||||||
bool_type_decorator, idx=idx,
|
bool_type_decorator, idx=idx,
|
||||||
bool_cols_are_tristate=
|
bool_cols_are_tristate=
|
||||||
|
@ -78,6 +78,7 @@ class BooksView(QTableView): # {{{
|
|||||||
self.pubdate_delegate = PubDateDelegate(self)
|
self.pubdate_delegate = PubDateDelegate(self)
|
||||||
self.tags_delegate = CompleteDelegate(self, ',', 'all_tags')
|
self.tags_delegate = CompleteDelegate(self, ',', 'all_tags')
|
||||||
self.authors_delegate = CompleteDelegate(self, '&', 'all_author_names', True)
|
self.authors_delegate = CompleteDelegate(self, '&', 'all_author_names', True)
|
||||||
|
self.cc_names_delegate = CompleteDelegate(self, '&', 'all_custom', True)
|
||||||
self.series_delegate = TextDelegate(self)
|
self.series_delegate = TextDelegate(self)
|
||||||
self.publisher_delegate = TextDelegate(self)
|
self.publisher_delegate = TextDelegate(self)
|
||||||
self.text_delegate = TextDelegate(self)
|
self.text_delegate = TextDelegate(self)
|
||||||
@ -410,6 +411,7 @@ class BooksView(QTableView): # {{{
|
|||||||
self.save_state()
|
self.save_state()
|
||||||
self._model.set_database(db)
|
self._model.set_database(db)
|
||||||
self.tags_delegate.set_database(db)
|
self.tags_delegate.set_database(db)
|
||||||
|
self.cc_names_delegate.set_database(db)
|
||||||
self.authors_delegate.set_database(db)
|
self.authors_delegate.set_database(db)
|
||||||
self.series_delegate.set_auto_complete_function(db.all_series)
|
self.series_delegate.set_auto_complete_function(db.all_series)
|
||||||
self.publisher_delegate.set_auto_complete_function(db.all_publishers)
|
self.publisher_delegate.set_auto_complete_function(db.all_publishers)
|
||||||
@ -431,12 +433,17 @@ class BooksView(QTableView): # {{{
|
|||||||
self.setItemDelegateForColumn(cm.index(colhead), delegate)
|
self.setItemDelegateForColumn(cm.index(colhead), delegate)
|
||||||
elif cc['datatype'] == 'comments':
|
elif cc['datatype'] == 'comments':
|
||||||
self.setItemDelegateForColumn(cm.index(colhead), self.cc_comments_delegate)
|
self.setItemDelegateForColumn(cm.index(colhead), self.cc_comments_delegate)
|
||||||
elif cc['datatype'] in ('text', 'series'):
|
elif cc['datatype'] == 'text':
|
||||||
if cc['is_multiple']:
|
if cc['is_multiple']:
|
||||||
self.setItemDelegateForColumn(cm.index(colhead), self.tags_delegate)
|
if cc['display'].get('is_names', False):
|
||||||
|
self.setItemDelegateForColumn(cm.index(colhead),
|
||||||
|
self.cc_names_delegate)
|
||||||
|
else:
|
||||||
|
self.setItemDelegateForColumn(cm.index(colhead),
|
||||||
|
self.tags_delegate)
|
||||||
else:
|
else:
|
||||||
self.setItemDelegateForColumn(cm.index(colhead), self.cc_text_delegate)
|
self.setItemDelegateForColumn(cm.index(colhead), self.cc_text_delegate)
|
||||||
elif cc['datatype'] in ('int', 'float'):
|
elif cc['datatype'] in ('series', 'int', 'float'):
|
||||||
self.setItemDelegateForColumn(cm.index(colhead), self.cc_text_delegate)
|
self.setItemDelegateForColumn(cm.index(colhead), self.cc_text_delegate)
|
||||||
elif cc['datatype'] == 'bool':
|
elif cc['datatype'] == 'bool':
|
||||||
self.setItemDelegateForColumn(cm.index(colhead), self.cc_bool_delegate)
|
self.setItemDelegateForColumn(cm.index(colhead), self.cc_bool_delegate)
|
||||||
|
@ -125,6 +125,8 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
self.datatype_changed()
|
self.datatype_changed()
|
||||||
if ct in ['text', 'composite', 'enumeration']:
|
if ct in ['text', 'composite', 'enumeration']:
|
||||||
self.use_decorations.setChecked(c['display'].get('use_decorations', False))
|
self.use_decorations.setChecked(c['display'].get('use_decorations', False))
|
||||||
|
elif ct == '*text':
|
||||||
|
self.is_names.setChecked(c['display'].get('is_names', False))
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
|
||||||
def shortcut_activated(self, url):
|
def shortcut_activated(self, url):
|
||||||
@ -167,6 +169,7 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
for x in ('box', 'default_label', 'label'):
|
for x in ('box', 'default_label', 'label'):
|
||||||
getattr(self, 'enum_'+x).setVisible(col_type == 'enumeration')
|
getattr(self, 'enum_'+x).setVisible(col_type == 'enumeration')
|
||||||
self.use_decorations.setVisible(col_type in ['text', 'composite', 'enumeration'])
|
self.use_decorations.setVisible(col_type in ['text', 'composite', 'enumeration'])
|
||||||
|
self.is_names.setVisible(col_type == '*text')
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
col = unicode(self.column_name_box.text()).strip()
|
col = unicode(self.column_name_box.text()).strip()
|
||||||
@ -241,6 +244,8 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
return self.simple_error('', _('The value "{0}" is in the '
|
return self.simple_error('', _('The value "{0}" is in the '
|
||||||
'list more than once').format(l[i]))
|
'list more than once').format(l[i]))
|
||||||
display_dict = {'enum_values': l}
|
display_dict = {'enum_values': l}
|
||||||
|
elif col_type == 'text' and is_multiple:
|
||||||
|
display_dict = {'is_names': self.is_names.isChecked()}
|
||||||
|
|
||||||
if col_type in ['text', 'composite', 'enumeration']:
|
if col_type in ['text', 'composite', 'enumeration']:
|
||||||
display_dict['use_decorations'] = self.use_decorations.checkState()
|
display_dict['use_decorations'] = self.use_decorations.checkState()
|
||||||
|
@ -120,6 +120,16 @@ Everything else will show nothing.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="is_names">
|
||||||
|
<property name="text">
|
||||||
|
<string>Contains names</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Check this box if this column contains names, like the authors column.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_27">
|
<spacer name="horizontalSpacer_27">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -65,7 +65,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
|
|
||||||
choices = set([k for k in db.field_metadata.all_field_keys()
|
choices = set([k for k in db.field_metadata.all_field_keys()
|
||||||
if db.field_metadata[k]['is_category'] and
|
if db.field_metadata[k]['is_category'] and
|
||||||
db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']])
|
(db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']) and
|
||||||
|
not db.field_metadata[k]['display'].get('is_names', False)])
|
||||||
choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
|
choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
|
||||||
choices |= set(['search'])
|
choices |= set(['search'])
|
||||||
self.opt_categories_using_hierarchy.update_items_cache(choices)
|
self.opt_categories_using_hierarchy.update_items_cache(choices)
|
||||||
|
@ -658,8 +658,7 @@ class TagTreeItem(object): # {{{
|
|||||||
|
|
||||||
def tag_data(self, role):
|
def tag_data(self, role):
|
||||||
tag = self.tag
|
tag = self.tag
|
||||||
if tag.category == 'authors' and \
|
if tag.use_sort_as_name:
|
||||||
tweaks['categories_use_field_for_author_name'] == 'author_sort':
|
|
||||||
name = tag.sort
|
name = tag.sort
|
||||||
tt_author = True
|
tt_author = True
|
||||||
else:
|
else:
|
||||||
@ -1275,6 +1274,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
if len(components) == 0 or '.'.join(components) != tag.original_name:
|
if len(components) == 0 or '.'.join(components) != tag.original_name:
|
||||||
components = [tag.original_name]
|
components = [tag.original_name]
|
||||||
if (not tag.is_hierarchical) and (in_uc or
|
if (not tag.is_hierarchical) and (in_uc or
|
||||||
|
(fm['is_custom'] and fm['display'].get('is_names', False)) or
|
||||||
key in ['authors', 'publisher', 'news', 'formats', 'rating'] or
|
key in ['authors', 'publisher', 'news', 'formats', 'rating'] or
|
||||||
key not in self.db.prefs.get('categories_using_hierarchy', []) or
|
key not in self.db.prefs.get('categories_using_hierarchy', []) or
|
||||||
len(components) == 1):
|
len(components) == 1):
|
||||||
|
@ -15,7 +15,7 @@ from calibre.utils.config import tweaks, prefs
|
|||||||
from calibre.utils.date import parse_date, now, UNDEFINED_DATE
|
from calibre.utils.date import parse_date, now, UNDEFINED_DATE
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
from calibre.utils.pyparsing import ParseException
|
from calibre.utils.pyparsing import ParseException
|
||||||
from calibre.ebooks.metadata import title_sort
|
from calibre.ebooks.metadata import title_sort, author_to_author_sort
|
||||||
from calibre.ebooks.metadata.opf2 import metadata_to_opf
|
from calibre.ebooks.metadata.opf2 import metadata_to_opf
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
|
|
||||||
@ -1023,6 +1023,10 @@ class SortKeyGenerator(object):
|
|||||||
if val:
|
if val:
|
||||||
sep = fm['is_multiple']
|
sep = fm['is_multiple']
|
||||||
if sep:
|
if sep:
|
||||||
|
if fm['display'].get('is_names', False):
|
||||||
|
val = sep.join(
|
||||||
|
[author_to_author_sort(v) for v in val.split(sep)])
|
||||||
|
else:
|
||||||
val = sep.join(sorted(val.split(sep),
|
val = sep.join(sorted(val.split(sep),
|
||||||
key=self.string_sort_key))
|
key=self.string_sort_key))
|
||||||
val = self.string_sort_key(val)
|
val = self.string_sort_key(val)
|
||||||
|
@ -117,7 +117,7 @@ class CustomColumns(object):
|
|||||||
if x is None:
|
if x is None:
|
||||||
return []
|
return []
|
||||||
if isinstance(x, (str, unicode, bytes)):
|
if isinstance(x, (str, unicode, bytes)):
|
||||||
x = x.split(',')
|
x = x.split('&' if d['display'].get('is_names', False) else',')
|
||||||
x = [y.strip() for y in x if y.strip()]
|
x = [y.strip() for y in x if y.strip()]
|
||||||
x = [y.decode(preferred_encoding, 'replace') if not isinstance(y,
|
x = [y.decode(preferred_encoding, 'replace') if not isinstance(y,
|
||||||
unicode) else y for y in x]
|
unicode) else y for y in x]
|
||||||
@ -482,8 +482,11 @@ class CustomColumns(object):
|
|||||||
set_val = val if data['is_multiple'] else [val]
|
set_val = val if data['is_multiple'] else [val]
|
||||||
existing = getter()
|
existing = getter()
|
||||||
if not existing:
|
if not existing:
|
||||||
existing = []
|
existing = set([])
|
||||||
for x in set(set_val) - set(existing):
|
else:
|
||||||
|
existing = set(existing)
|
||||||
|
# preserve the order in set_val
|
||||||
|
for x in [v for v in set_val if v not in existing]:
|
||||||
# normalized types are text and ratings, so we can do this check
|
# normalized types are text and ratings, so we can do this check
|
||||||
# to see if we need to re-add the value
|
# to see if we need to re-add the value
|
||||||
if not x:
|
if not x:
|
||||||
|
@ -48,7 +48,7 @@ class Tag(object):
|
|||||||
|
|
||||||
def __init__(self, name, id=None, count=0, state=0, avg=0, sort=None,
|
def __init__(self, name, id=None, count=0, state=0, avg=0, sort=None,
|
||||||
tooltip=None, icon=None, category=None, id_set=None,
|
tooltip=None, icon=None, category=None, id_set=None,
|
||||||
is_editable = True, is_searchable=True):
|
is_editable = True, is_searchable=True, use_sort_as_name=False):
|
||||||
self.name = self.original_name = name
|
self.name = self.original_name = name
|
||||||
self.id = id
|
self.id = id
|
||||||
self.count = count
|
self.count = count
|
||||||
@ -59,6 +59,7 @@ class Tag(object):
|
|||||||
self.id_set = id_set if id_set is not None else set([])
|
self.id_set = id_set if id_set is not None else set([])
|
||||||
self.avg_rating = avg/2.0 if avg is not None else 0
|
self.avg_rating = avg/2.0 if avg is not None else 0
|
||||||
self.sort = sort
|
self.sort = sort
|
||||||
|
self.use_sort_as_name = use_sort_as_name
|
||||||
if self.avg_rating > 0:
|
if self.avg_rating > 0:
|
||||||
if tooltip:
|
if tooltip:
|
||||||
tooltip = tooltip + ': '
|
tooltip = tooltip + ': '
|
||||||
@ -1323,6 +1324,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
for l in list:
|
for l in list:
|
||||||
(id, val) = (l[0], l[1])
|
(id, val) = (l[0], l[1])
|
||||||
tids[category][val] = (id, '{0:05.2f}'.format(val))
|
tids[category][val] = (id, '{0:05.2f}'.format(val))
|
||||||
|
elif cat['datatype'] == 'text' and cat['is_multiple'] and \
|
||||||
|
cat['display'].get('is_names', False):
|
||||||
|
for l in list:
|
||||||
|
(id, val) = (l[0], l[1])
|
||||||
|
tids[category][val] = (id, author_to_author_sort(val))
|
||||||
else:
|
else:
|
||||||
for l in list:
|
for l in list:
|
||||||
(id, val) = (l[0], l[1])
|
(id, val) = (l[0], l[1])
|
||||||
@ -1480,11 +1486,20 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
reverse=True
|
reverse=True
|
||||||
items.sort(key=kf, reverse=reverse)
|
items.sort(key=kf, reverse=reverse)
|
||||||
|
|
||||||
|
if tweaks['categories_use_field_for_author_name'] == 'author_sort' and\
|
||||||
|
(category == 'authors' or
|
||||||
|
(cat['display'].get('is_names', False) and
|
||||||
|
cat['is_custom'] and cat['is_multiple'] and
|
||||||
|
cat['datatype'] == 'text')):
|
||||||
|
use_sort_as_name = True
|
||||||
|
else:
|
||||||
|
use_sort_as_name = False
|
||||||
is_editable = category not in ['news', 'rating']
|
is_editable = category not in ['news', 'rating']
|
||||||
categories[category] = [tag_class(formatter(r.n), count=r.c, id=r.id,
|
categories[category] = [tag_class(formatter(r.n), count=r.c, id=r.id,
|
||||||
avg=avgr(r), sort=r.s, icon=icon,
|
avg=avgr(r), sort=r.s, icon=icon,
|
||||||
tooltip=tooltip, category=category,
|
tooltip=tooltip, category=category,
|
||||||
id_set=r.id_set, is_editable=is_editable)
|
id_set=r.id_set, is_editable=is_editable,
|
||||||
|
use_sort_as_name=use_sort_as_name)
|
||||||
for r in items]
|
for r in items]
|
||||||
|
|
||||||
#print 'end phase "tags list":', time.clock() - last, 'seconds'
|
#print 'end phase "tags list":', time.clock() - last, 'seconds'
|
||||||
|
@ -15,7 +15,7 @@ from calibre import isbytestring, force_unicode, fit_image, \
|
|||||||
prepare_string_for_xml
|
prepare_string_for_xml
|
||||||
from calibre.utils.ordered_dict import OrderedDict
|
from calibre.utils.ordered_dict import OrderedDict
|
||||||
from calibre.utils.filenames import ascii_filename
|
from calibre.utils.filenames import ascii_filename
|
||||||
from calibre.utils.config import prefs, tweaks
|
from calibre.utils.config import prefs
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
from calibre.utils.magick import Image
|
from calibre.utils.magick import Image
|
||||||
from calibre.library.comments import comments_to_html
|
from calibre.library.comments import comments_to_html
|
||||||
@ -155,8 +155,7 @@ def get_category_items(category, items, restriction, datatype, prefix): # {{{
|
|||||||
'<div>{1}</div>'
|
'<div>{1}</div>'
|
||||||
'<div>{2}</div></div>')
|
'<div>{2}</div></div>')
|
||||||
rating, rstring = render_rating(i.avg_rating, prefix)
|
rating, rstring = render_rating(i.avg_rating, prefix)
|
||||||
if i.category == 'authors' and \
|
if i.use_sort_as_name:
|
||||||
tweaks['categories_use_field_for_author_name'] == 'author_sort':
|
|
||||||
name = xml(i.sort)
|
name = xml(i.sort)
|
||||||
else:
|
else:
|
||||||
name = xml(i.name)
|
name = xml(i.name)
|
||||||
@ -696,7 +695,10 @@ class BrowseServer(object):
|
|||||||
xml(href, True),
|
xml(href, True),
|
||||||
xml(val if len(dbtags) == 1 else tag.name),
|
xml(val if len(dbtags) == 1 else tag.name),
|
||||||
xml(key, True)))
|
xml(key, True)))
|
||||||
join = ' & ' if key == 'authors' else ', '
|
join = ' & ' if key == 'authors' or \
|
||||||
|
(fm['is_custom'] and
|
||||||
|
fm['display'].get('is_names', False)) \
|
||||||
|
else ', '
|
||||||
args[key] = join.join(vals)
|
args[key] = join.join(vals)
|
||||||
added_key = True
|
added_key = True
|
||||||
if not added_key:
|
if not added_key:
|
||||||
|
@ -22,7 +22,6 @@ from calibre.library.server.utils import format_tag_string, Offsets
|
|||||||
from calibre import guess_type, prepare_string_for_xml as xml
|
from calibre import guess_type, prepare_string_for_xml as xml
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
from calibre.utils.ordered_dict import OrderedDict
|
from calibre.utils.ordered_dict import OrderedDict
|
||||||
from calibre.utils.config import tweaks
|
|
||||||
|
|
||||||
BASE_HREFS = {
|
BASE_HREFS = {
|
||||||
0 : '/stanza',
|
0 : '/stanza',
|
||||||
@ -126,8 +125,7 @@ def CATALOG_ENTRY(item, item_kind, base_href, version, updated,
|
|||||||
count = (_('%d books') if item.count > 1 else _('%d book'))%item.count
|
count = (_('%d books') if item.count > 1 else _('%d book'))%item.count
|
||||||
if ignore_count:
|
if ignore_count:
|
||||||
count = ''
|
count = ''
|
||||||
if item.category == 'authors' and \
|
if item.use_sort_as_name:
|
||||||
tweaks['categories_use_field_for_author_name'] == 'author_sort':
|
|
||||||
name = item.sort
|
name = item.sort
|
||||||
else:
|
else:
|
||||||
name = item.name
|
name = item.name
|
||||||
|
Loading…
x
Reference in New Issue
Block a user