mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Author link first try
This commit is contained in:
parent
52edcbe991
commit
034e289ef3
@ -86,6 +86,8 @@ CALIBRE_METADATA_FIELDS = frozenset([
|
||||
# a dict of user category names, where the value is a list of item names
|
||||
# from the book that are in that category
|
||||
'user_categories',
|
||||
# a dict of author to an associated hyperlink
|
||||
'author_link_map',
|
||||
|
||||
]
|
||||
)
|
||||
|
@ -34,6 +34,7 @@ NULL_VALUES = {
|
||||
'authors' : [_('Unknown')],
|
||||
'title' : _('Unknown'),
|
||||
'user_categories' : {},
|
||||
'author_link_map' : {},
|
||||
'language' : 'und'
|
||||
}
|
||||
|
||||
|
@ -538,7 +538,8 @@ class OPF(object): # {{{
|
||||
user_categories = MetadataField('user_categories', is_dc=False,
|
||||
formatter=json.loads,
|
||||
renderer=dump_user_categories)
|
||||
|
||||
author_link_map = MetadataField('author_link_map', is_dc=False,
|
||||
formatter=json.loads)
|
||||
|
||||
def __init__(self, stream, basedir=os.getcwdu(), unquote_urls=True,
|
||||
populate_spine=True):
|
||||
@ -1039,7 +1040,7 @@ class OPF(object): # {{{
|
||||
for attr in ('title', 'authors', 'author_sort', 'title_sort',
|
||||
'publisher', 'series', 'series_index', 'rating',
|
||||
'isbn', 'tags', 'category', 'comments',
|
||||
'pubdate', 'user_categories'):
|
||||
'pubdate', 'user_categories', 'author_link_map'):
|
||||
val = getattr(mi, attr, None)
|
||||
if val is not None and val != [] and val != (None, None):
|
||||
setattr(self, attr, val)
|
||||
@ -1336,6 +1337,8 @@ def metadata_to_opf(mi, as_string=True):
|
||||
for tag in mi.tags:
|
||||
factory(DC('subject'), tag)
|
||||
meta = lambda n, c: factory('meta', name='calibre:'+n, content=c)
|
||||
if getattr(mi, 'author_link_map', None) is not None:
|
||||
meta('author_link_map', json.dumps(mi.author_link_map))
|
||||
if mi.series:
|
||||
meta('series', mi.series)
|
||||
if mi.series_index is not None:
|
||||
|
@ -121,6 +121,16 @@ def render_data(mi, use_roman_numbers=True, all_fields=False):
|
||||
if links:
|
||||
ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(
|
||||
_('Ids')+':', links)))
|
||||
elif field == 'authors' and not isdevice:
|
||||
authors = []
|
||||
for aut in mi.authors:
|
||||
if mi.author_link_map[aut]:
|
||||
authors.append(u'<a href="%s">%s</a>' %
|
||||
(mi.author_link_map[aut], aut))
|
||||
else:
|
||||
authors.append(aut)
|
||||
ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name,
|
||||
u' & '.join(authors))))
|
||||
else:
|
||||
val = mi.format_field(field)[-1]
|
||||
if val is None:
|
||||
|
@ -33,7 +33,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
|
||||
|
||||
# Set up the column headings
|
||||
self.table.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.table.setColumnCount(2)
|
||||
self.table.setColumnCount(3)
|
||||
self.down_arrow_icon = QIcon(I('arrow-down.png'))
|
||||
self.up_arrow_icon = QIcon(I('arrow-up.png'))
|
||||
self.blank_icon = QIcon(I('blank.png'))
|
||||
@ -43,26 +43,33 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
|
||||
self.aus_col = QTableWidgetItem(_('Author sort'))
|
||||
self.table.setHorizontalHeaderItem(1, self.aus_col)
|
||||
self.aus_col.setIcon(self.up_arrow_icon)
|
||||
self.aul_col = QTableWidgetItem(_('Link'))
|
||||
self.table.setHorizontalHeaderItem(2, self.aul_col)
|
||||
self.aus_col.setIcon(self.blank_icon)
|
||||
|
||||
# Add the data
|
||||
self.authors = {}
|
||||
auts = db.get_authors_with_ids()
|
||||
self.table.setRowCount(len(auts))
|
||||
select_item = None
|
||||
for row, (id, author, sort) in enumerate(auts):
|
||||
for row, (id, author, sort, link) in enumerate(auts):
|
||||
author = author.replace('|', ',')
|
||||
self.authors[id] = (author, sort)
|
||||
self.authors[id] = (author, sort, link)
|
||||
aut = tableItem(author)
|
||||
aut.setData(Qt.UserRole, id)
|
||||
sort = tableItem(sort)
|
||||
link = tableItem(link)
|
||||
self.table.setItem(row, 0, aut)
|
||||
self.table.setItem(row, 1, sort)
|
||||
self.table.setItem(row, 2, link)
|
||||
if id == id_to_select:
|
||||
if select_sort:
|
||||
select_item = sort
|
||||
else:
|
||||
select_item = aut
|
||||
self.table.resizeColumnsToContents()
|
||||
if self.table.columnWidth(2) < 200:
|
||||
self.table.setColumnWidth(2, 200)
|
||||
|
||||
# set up the cellChanged signal only after the table is filled
|
||||
self.table.cellChanged.connect(self.cell_changed)
|
||||
@ -236,9 +243,10 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
|
||||
id = self.table.item(row, 0).data(Qt.UserRole).toInt()[0]
|
||||
aut = unicode(self.table.item(row, 0).text()).strip()
|
||||
sort = unicode(self.table.item(row, 1).text()).strip()
|
||||
orig_aut,orig_sort = self.authors[id]
|
||||
if orig_aut != aut or orig_sort != sort:
|
||||
self.result.append((id, orig_aut, aut, sort))
|
||||
link = unicode(self.table.item(row, 2).text()).strip()
|
||||
orig_aut,orig_sort,orig_link = self.authors[id]
|
||||
if orig_aut != aut or orig_sort != sort or orig_link != link:
|
||||
self.result.append((id, orig_aut, aut, sort, link))
|
||||
|
||||
def do_recalc_author_sort(self):
|
||||
self.table.cellChanged.disconnect()
|
||||
@ -276,6 +284,6 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
|
||||
c.setText(author_to_author_sort(aut))
|
||||
item = c
|
||||
else:
|
||||
item = self.table.item(row, 1)
|
||||
item = self.table.item(row, col)
|
||||
self.table.setCurrentItem(item)
|
||||
self.table.scrollToItem(item)
|
||||
|
@ -90,6 +90,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
self.ids_to_highlight_set = set()
|
||||
self.current_highlighted_idx = None
|
||||
self.highlight_only = False
|
||||
self.current_row = -1
|
||||
self.colors = frozenset([unicode(c) for c in QColor.colorNames()])
|
||||
self.read_config()
|
||||
|
||||
@ -172,6 +173,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
self.color_cache = defaultdict(dict)
|
||||
for row in rows:
|
||||
if row == current_row:
|
||||
self.current_row = row
|
||||
self.new_bookdisplay_data.emit(
|
||||
self.get_book_display_info(row))
|
||||
self.dataChanged.emit(self.index(row, 0), self.index(row,
|
||||
@ -329,6 +331,8 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
def refresh(self, reset=True):
|
||||
self.db.refresh(field=None)
|
||||
self.resort(reset=reset)
|
||||
if self.current_row >= 0:
|
||||
self.new_bookdisplay_data.emit(self.get_book_display_info(self.current_row))
|
||||
|
||||
def reset(self):
|
||||
self.color_cache = defaultdict(dict)
|
||||
@ -368,12 +372,14 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
|
||||
def current_changed(self, current, previous, emit_signal=True):
|
||||
if current.isValid():
|
||||
idx = current.row()
|
||||
self.current_row = idx = current.row()
|
||||
data = self.get_book_display_info(idx)
|
||||
if emit_signal:
|
||||
self.new_bookdisplay_data.emit(data)
|
||||
else:
|
||||
return data
|
||||
else:
|
||||
self.current_row = -1
|
||||
|
||||
def get_book_info(self, index):
|
||||
if isinstance(index, int):
|
||||
|
@ -2081,12 +2081,14 @@ class TagBrowserMixin(object): # {{{
|
||||
editor = EditAuthorsDialog(parent, db, id, select_sort)
|
||||
d = editor.exec_()
|
||||
if d:
|
||||
for (id, old_author, new_author, new_sort) in editor.result:
|
||||
for (id, old_author, new_author, new_sort, new_link) in editor.result:
|
||||
if old_author != new_author:
|
||||
# The id might change if the new author already exists
|
||||
id = db.rename_author(id, new_author)
|
||||
db.set_sort_field_for_author(id, unicode(new_sort),
|
||||
commit=False, notify=False)
|
||||
db.set_link_field_for_author(id, unicode(new_link),
|
||||
commit=False, notify=False)
|
||||
db.commit()
|
||||
self.library_view.model().refresh()
|
||||
self.tags_view.recount()
|
||||
|
@ -367,7 +367,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
'uuid',
|
||||
'has_cover',
|
||||
('au_map', 'authors', 'author',
|
||||
'aum_sortconcat(link.id, authors.name, authors.sort)'),
|
||||
'aum_sortconcat(link.id, authors.name, authors.sort, authors.link)'),
|
||||
'last_modified',
|
||||
'(SELECT identifiers_concat(type, val) FROM identifiers WHERE identifiers.book=books.id) identifiers',
|
||||
]
|
||||
@ -894,13 +894,17 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
aut_list = []
|
||||
aum = []
|
||||
aus = {}
|
||||
for (author, author_sort) in aut_list:
|
||||
aum.append(author.replace('|', ','))
|
||||
aus[author] = author_sort.replace('|', ',')
|
||||
aul = {}
|
||||
for (author, author_sort, link) in aut_list:
|
||||
aut = author.replace('|', ',')
|
||||
aum.append(aut)
|
||||
aus[aut] = author_sort.replace('|', ',')
|
||||
aul[aut] = link
|
||||
mi.title = row[fm['title']]
|
||||
mi.authors = aum
|
||||
mi.author_sort = row[fm['author_sort']]
|
||||
mi.author_sort_map = aus
|
||||
mi.author_link_map = aul
|
||||
mi.comments = row[fm['comments']]
|
||||
mi.publisher = row[fm['publisher']]
|
||||
mi.timestamp = row[fm['timestamp']]
|
||||
@ -2002,13 +2006,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
def authors_with_sort_strings(self, id, index_is_id=False):
|
||||
id = id if index_is_id else self.id(id)
|
||||
aut_strings = self.conn.get('''
|
||||
SELECT authors.id, authors.name, authors.sort
|
||||
SELECT authors.id, authors.name, authors.sort, authors.link
|
||||
FROM authors, books_authors_link as bl
|
||||
WHERE bl.book=? and authors.id=bl.author
|
||||
ORDER BY bl.id''', (id,))
|
||||
result = []
|
||||
for (id_, author, sort,) in aut_strings:
|
||||
result.append((id_, author.replace('|', ','), sort))
|
||||
for (id_, author, sort, link) in aut_strings:
|
||||
result.append((id_, author.replace('|', ','), sort, link))
|
||||
return result
|
||||
|
||||
# Given a book, return the author_sort string for authors of the book
|
||||
@ -2048,7 +2052,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
|
||||
aum = self.authors_with_sort_strings(id_, index_is_id=True)
|
||||
self.data.set(id_, self.FIELD_MAP['au_map'],
|
||||
':#:'.join([':::'.join((au.replace(',', '|'), aus)) for (_, au, aus) in aum]),
|
||||
':#:'.join([':::'.join((au.replace(',', '|'), aus, aul))
|
||||
for (_, au, aus, aul) in aum]),
|
||||
row_is_id=True)
|
||||
|
||||
def _set_authors(self, id, authors, allow_case_change=False):
|
||||
@ -2399,7 +2404,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
self.conn.commit()
|
||||
|
||||
def get_authors_with_ids(self):
|
||||
result = self.conn.get('SELECT id,name,sort FROM authors')
|
||||
result = self.conn.get('SELECT id,name,sort,link FROM authors')
|
||||
if not result:
|
||||
return []
|
||||
return result
|
||||
@ -2410,6 +2415,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
(author,), all=False)
|
||||
return result
|
||||
|
||||
def set_link_field_for_author(self, aid, link, commit=True, notify=False):
|
||||
if not link:
|
||||
link = ''
|
||||
self.conn.execute('UPDATE authors SET link=? WHERE id=?', (link.strip(), aid))
|
||||
if commit:
|
||||
self.conn.commit()
|
||||
|
||||
def set_sort_field_for_author(self, old_id, new_sort, commit=True, notify=False):
|
||||
self.conn.execute('UPDATE authors SET sort=? WHERE id=?', \
|
||||
(new_sort.strip(), old_id))
|
||||
|
@ -600,4 +600,14 @@ class SchemaUpgrade(object):
|
||||
with open(os.path.join(bdir, fname), 'wb') as f:
|
||||
f.write(script)
|
||||
|
||||
def upgrade_version_20(self):
|
||||
'''
|
||||
Add a link column to the authors table.
|
||||
'''
|
||||
|
||||
script = '''
|
||||
ALTER TABLE authors ADD COLUMN link TEXT NON NULL DEFAULT "";
|
||||
'''
|
||||
self.conn.executescript(script)
|
||||
|
||||
|
||||
|
@ -144,9 +144,9 @@ class AumSortedConcatenate(object):
|
||||
def __init__(self):
|
||||
self.ans = {}
|
||||
|
||||
def step(self, ndx, author, sort):
|
||||
def step(self, ndx, author, sort, link):
|
||||
if author is not None:
|
||||
self.ans[ndx] = author + ':::' + sort
|
||||
self.ans[ndx] = ':::'.join((author, sort, link))
|
||||
|
||||
def finalize(self):
|
||||
keys = self.ans.keys()
|
||||
@ -229,7 +229,7 @@ class DBThread(Thread):
|
||||
load_c_extensions(self.conn)
|
||||
self.conn.row_factory = sqlite.Row if self.row_factory else lambda cursor, row : list(row)
|
||||
self.conn.create_aggregate('concat', 1, Concatenate)
|
||||
self.conn.create_aggregate('aum_sortconcat', 3, AumSortedConcatenate)
|
||||
self.conn.create_aggregate('aum_sortconcat', 4, AumSortedConcatenate)
|
||||
self.conn.create_collation('PYNOCASE', partial(pynocase,
|
||||
encoding=encoding))
|
||||
self.conn.create_function('title_sort', 1, title_sort)
|
||||
|
Loading…
x
Reference in New Issue
Block a user