mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement #1068 (Multiple authors vs. Standards)
This commit is contained in:
parent
0d8425469e
commit
206da41869
@ -15,6 +15,24 @@ from calibre.constants import __version__ as VERSION
|
||||
from calibre import relpath
|
||||
from calibre.utils.config import OptionParser
|
||||
|
||||
def string_to_authors(raw):
|
||||
raw = raw.replace('&&', u'\uffff')
|
||||
authors = [a.strip().replace(u'\uffff', '&') for a in raw.split('&')]
|
||||
return authors
|
||||
|
||||
def authors_to_string(authors):
|
||||
return ' & '.join([a.replace('&', '&&') for a in authors])
|
||||
|
||||
def author_to_author_sort(author):
|
||||
tokens = author.split()
|
||||
tokens = tokens[-1:] + tokens[:-1]
|
||||
if len(tokens) > 1:
|
||||
tokens[0] += ','
|
||||
return ' '.join(tokens)
|
||||
|
||||
def authors_to_sort_string(authors):
|
||||
return ' & '.join(map(author_to_author_sort, authors))
|
||||
|
||||
def get_parser(extension):
|
||||
''' Return an option parser with the basic metadata options already setup'''
|
||||
parser = OptionParser(usage='%prog [options] myfile.'+extension+'\n\nRead and write metadata from an ebook file.')
|
||||
|
@ -7,8 +7,10 @@ __docformat__ = 'restructuredtext en'
|
||||
The GUI for conversion to EPUB.
|
||||
'''
|
||||
import os
|
||||
|
||||
from PyQt4.Qt import QDialog, QSpinBox, QDoubleSpinBox, QComboBox, QLineEdit, \
|
||||
QTextEdit, QCheckBox, Qt, QPixmap, QIcon, QListWidgetItem, SIGNAL
|
||||
from lxml.etree import XPath
|
||||
|
||||
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
||||
from calibre.gui2.dialogs.epub_ui import Ui_Dialog
|
||||
@ -17,7 +19,8 @@ from calibre.ebooks.epub.from_any import SOURCE_FORMATS, config
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.ebooks.metadata.opf import OPFCreator
|
||||
from lxml.etree import XPath
|
||||
from calibre.ebooks.metadata import authors_to_string, string_to_authors
|
||||
|
||||
|
||||
class Config(QDialog, Ui_Dialog):
|
||||
|
||||
@ -128,7 +131,10 @@ class Config(QDialog, Ui_Dialog):
|
||||
if self.row is not None:
|
||||
mi = self.db.get_metadata(self.id, index_is_id=True)
|
||||
self.title.setText(mi.title)
|
||||
self.author.setText(', '.join(mi.authors))
|
||||
if mi.authors:
|
||||
self.author.setText(authors_to_string(mi.authors))
|
||||
else:
|
||||
self.author.setText('')
|
||||
self.publisher.setText(mi.publisher if mi.publisher else '')
|
||||
self.author_sort.setText(mi.author_sort if mi.author_sort else '')
|
||||
self.tags.setText(', '.join(mi.tags if mi.tags else []))
|
||||
@ -149,9 +155,8 @@ class Config(QDialog, Ui_Dialog):
|
||||
title = unicode(self.title.text()).strip()
|
||||
if not title:
|
||||
title = _('Unknown')
|
||||
authors = [i.strip() for i in unicode(self.author.text()).strip().split(',')]
|
||||
if not authors:
|
||||
authors = [_('Unknown')]
|
||||
authors = unicode(self.author.text()).strip()
|
||||
authors = string_to_authors(authors) if authors else [_('Unknown')]
|
||||
return title, authors
|
||||
|
||||
def get_metadata(self):
|
||||
|
@ -77,7 +77,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stack" >
|
||||
<property name="currentIndex" >
|
||||
<number>3</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="metadata_page" >
|
||||
<layout class="QGridLayout" name="gridLayout_4" >
|
||||
@ -221,7 +221,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by a comma</string>
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by an &. If the author name contains an &, use && to represent it.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -14,6 +14,7 @@ from calibre.gui2.widgets import FontFamilyModel
|
||||
from calibre.ebooks.lrf import option_parser
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.constants import __appname__
|
||||
from calibre.ebooks.metadata import authors_to_string, string_to_authors, authors_to_sort_string
|
||||
|
||||
font_family_model = None
|
||||
|
||||
@ -199,7 +200,11 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
||||
self.id = self.db.id(row)
|
||||
self.gui_title.setText(db.title(row))
|
||||
au = self.db.authors(row)
|
||||
self.gui_author.setText(au if au else '')
|
||||
if au:
|
||||
au = [a.strip().replace('|', ',') for a in au.split(',')]
|
||||
self.gui_author.setText(authors_to_string(au))
|
||||
else:
|
||||
self.gui_author.setText('')
|
||||
aus = self.db.author_sort(row)
|
||||
self.gui_author_sort.setText(aus if aus else '')
|
||||
pub = self.db.publisher(row)
|
||||
@ -350,14 +355,16 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
||||
def write_metadata(self):
|
||||
title = qstring_to_unicode(self.gui_title.text())
|
||||
self.db.set_title(self.id, title)
|
||||
au = qstring_to_unicode(self.gui_author.text()).split(',')
|
||||
if au: self.db.set_authors(self.id, au)
|
||||
au = unicode(self.gui_author.text())
|
||||
if au:
|
||||
self.db.set_authors(self.id, string_to_authors(au))
|
||||
aus = qstring_to_unicode(self.gui_author_sort.text())
|
||||
if not aus:
|
||||
t = self.db.authors(self.id, index_is_id=True)
|
||||
if not t:
|
||||
t = 'Unknown'
|
||||
aus = t.split(',')[0].strip()
|
||||
t = _('Unknown')
|
||||
aus = [a.strip().replace('|', ',') for a in t.split(',')]
|
||||
aus = authors_to_sort_string(aus)
|
||||
self.db.set_author_sort(self.id, aus)
|
||||
self.db.set_publisher(self.id, qstring_to_unicode(self.gui_publisher.text()))
|
||||
self.db.set_tags(self.id, qstring_to_unicode(self.tags.text()).split(','))
|
||||
|
@ -115,7 +115,7 @@
|
||||
<item row="0" column="0" >
|
||||
<widget class="QStackedWidget" name="stack" >
|
||||
<property name="currentIndex" >
|
||||
<number>3</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="metadata_page" >
|
||||
<layout class="QHBoxLayout" >
|
||||
@ -255,7 +255,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by a comma</string>
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by an &. If the author name contains an &, use && to represent it.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -9,6 +9,7 @@ from PyQt4.QtGui import QDialog
|
||||
from calibre.gui2 import qstring_to_unicode
|
||||
from calibre.gui2.dialogs.metadata_bulk_ui import Ui_MetadataBulkDialog
|
||||
from calibre.gui2.dialogs.tag_editor import TagEditor
|
||||
from calibre.ebooks.metadata import string_to_authors
|
||||
|
||||
class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
def __init__(self, window, rows, db):
|
||||
@ -51,7 +52,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
for id in self.ids:
|
||||
au = qstring_to_unicode(self.authors.text())
|
||||
if au:
|
||||
au = au.split(',')
|
||||
au = string_to_authors(au)
|
||||
self.db.set_authors(id, au)
|
||||
aus = qstring_to_unicode(self.author_sort.text())
|
||||
if aus:
|
||||
|
@ -52,7 +52,7 @@
|
||||
<item row="0" column="1" colspan="2" >
|
||||
<widget class="QLineEdit" name="authors" >
|
||||
<property name="toolTip" >
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by a comma</string>
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by an &. If the author name contains an &, use && to represent it.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -84,6 +84,9 @@
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>rating</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2" >
|
||||
|
@ -17,6 +17,7 @@ from calibre.gui2.dialogs.fetch_metadata import FetchMetadata
|
||||
from calibre.gui2.dialogs.tag_editor import TagEditor
|
||||
from calibre.gui2.dialogs.password import PasswordDialog
|
||||
from calibre.ebooks import BOOK_EXTENSIONS
|
||||
from calibre.ebooks.metadata import authors_to_sort_string, string_to_authors, authors_to_string
|
||||
from calibre.ebooks.metadata.library_thing import login, cover_from_isbn, LibraryThingError
|
||||
from calibre import islinux
|
||||
from calibre.utils.config import prefs
|
||||
@ -155,7 +156,11 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
isbn = ''
|
||||
self.isbn.setText(isbn)
|
||||
au = self.db.authors(row)
|
||||
self.authors.setText(au if au else '')
|
||||
if au:
|
||||
au = [a.strip().replace('|', ',') for a in au.split(',')]
|
||||
self.authors.setText(authors_to_string(au))
|
||||
else:
|
||||
self.authors.setText('')
|
||||
aus = self.db.author_sort(row)
|
||||
self.author_sort.setText(aus if aus else '')
|
||||
pub = self.db.publisher(row)
|
||||
@ -199,13 +204,8 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
|
||||
def deduce_author_sort(self):
|
||||
au = unicode(self.authors.text())
|
||||
tokens = au.split()
|
||||
for x in (',', ';'):
|
||||
if x in tokens:
|
||||
tokens.remove(x)
|
||||
if tokens:
|
||||
tokens = [tokens[-1]+';'] + tokens[:-1]
|
||||
self.author_sort.setText(u' '.join(tokens))
|
||||
authors = string_to_authors(au)
|
||||
self.author_sort.setText(authors_to_sort_string(authors))
|
||||
|
||||
def swap_title_author(self):
|
||||
title = self.title.text()
|
||||
@ -293,7 +293,7 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
def fetch_metadata(self):
|
||||
isbn = qstring_to_unicode(self.isbn.text())
|
||||
title = qstring_to_unicode(self.title.text())
|
||||
author = qstring_to_unicode(self.authors.text()).split(',')[0]
|
||||
author = string_to_authors(unicode(self.authors.text()))[0]
|
||||
publisher = qstring_to_unicode(self.publisher.text())
|
||||
if isbn or title or author or publisher:
|
||||
d = FetchMetadata(self, isbn, title, author, publisher, self.timeout)
|
||||
@ -302,7 +302,7 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
book = d.selected_book()
|
||||
if book:
|
||||
self.title.setText(book.title)
|
||||
self.authors.setText(', '.join(book.authors))
|
||||
self.authors.setText(authors_to_string(book.authors))
|
||||
if book.author_sort: self.author_sort.setText(book.author_sort)
|
||||
if book.publisher: self.publisher.setText(book.publisher)
|
||||
if book.isbn: self.isbn.setText(book.isbn)
|
||||
@ -335,8 +335,9 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
self.sync_formats()
|
||||
title = qstring_to_unicode(self.title.text())
|
||||
self.db.set_title(self.id, title)
|
||||
au = qstring_to_unicode(self.authors.text()).split(',')
|
||||
if au: self.db.set_authors(self.id, au)
|
||||
au = unicode(self.authors.text())
|
||||
if au:
|
||||
self.db.set_authors(self.id, string_to_authors(au))
|
||||
aus = qstring_to_unicode(self.author_sort.text())
|
||||
if aus:
|
||||
self.db.set_author_sort(self.id, aus)
|
||||
|
@ -98,7 +98,7 @@
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="authors" >
|
||||
<property name="toolTip" >
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by a comma</string>
|
||||
<string>Change the author(s) of this book. Multiple authors should be separated by an &. If the author name contains an &, use && to represent it.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -548,8 +548,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>af_group_box</zorder>
|
||||
<zorder>groupBox_4</zorder>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -381,7 +381,7 @@ class BooksModel(QAbstractTableModel):
|
||||
elif col == 1:
|
||||
au = self.db.authors(row)
|
||||
if au:
|
||||
au = au.split(',')
|
||||
au = [a.strip().replace('|', ',') for a in au.split(',')]
|
||||
return QVariant("\n".join(au))
|
||||
elif col == 2:
|
||||
size = self.db.max_size(row)
|
||||
|
@ -910,7 +910,10 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
return _('Unknown')
|
||||
|
||||
def authors(self, index, index_is_id=False):
|
||||
''' Authors as a comma separated list or None'''
|
||||
'''
|
||||
Authors as a comma separated list or None.
|
||||
In the comma separated list, commas in author names are replaced by | symbols
|
||||
'''
|
||||
if not index_is_id:
|
||||
return self.data[index][2]
|
||||
try:
|
||||
@ -1361,7 +1364,7 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
Convenience method to return metadata as a L{MetaInformation} object.
|
||||
'''
|
||||
aum = self.authors(idx, index_is_id=index_is_id)
|
||||
if aum: aum = aum.split(',')
|
||||
if aum: aum = [a.strip().replace('|', ',') for a in aum.split(',')]
|
||||
mi = MetaInformation(self.title(idx, index_is_id=index_is_id), aum)
|
||||
mi.author_sort = self.author_sort(idx, index_is_id=index_is_id)
|
||||
mi.comments = self.comments(idx, index_is_id=index_is_id)
|
||||
|
@ -16,6 +16,7 @@ from PyQt4.QtGui import QApplication, QPixmap, QImage
|
||||
__app = None
|
||||
|
||||
from calibre.library.database import LibraryDatabase
|
||||
from calibre.ebooks.metadata import string_to_authors
|
||||
from calibre.constants import preferred_encoding
|
||||
|
||||
copyfile = os.link if hasattr(os, 'link') else shutil.copyfile
|
||||
@ -732,7 +733,7 @@ class LibraryDatabase2(LibraryDatabase):
|
||||
|
||||
self.data.set(row, col, val)
|
||||
if column == 'authors':
|
||||
val = val.split('&,')
|
||||
val = string_to_authors(val)
|
||||
self.set_authors(id, val, notify=False)
|
||||
elif column == 'title':
|
||||
self.set_title(id, val, notify=False)
|
||||
@ -742,6 +743,7 @@ class LibraryDatabase2(LibraryDatabase):
|
||||
self.set_rating(id, val)
|
||||
elif column == 'tags':
|
||||
self.set_tags(id, val.split(','), append=False, notify=False)
|
||||
self.data.refresh_ids(self.conn, [id])
|
||||
self.set_path(id, True)
|
||||
self.notify('metadata', [id])
|
||||
|
||||
@ -783,7 +785,7 @@ class LibraryDatabase2(LibraryDatabase):
|
||||
for a in authors:
|
||||
if not a:
|
||||
continue
|
||||
a = a.strip()
|
||||
a = a.strip().replace(',', '|')
|
||||
if not isinstance(a, unicode):
|
||||
a = a.decode(preferred_encoding, 'replace')
|
||||
author = self.conn.execute('SELECT id from authors WHERE name=?', (a,)).fetchone()
|
||||
|
Loading…
x
Reference in New Issue
Block a user