mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
7f7804814c
@ -48,7 +48,7 @@ class LeMonde(BasicNewsRecipe):
|
|||||||
if alink.string is not None:
|
if alink.string is not None:
|
||||||
tstr = alink.string
|
tstr = alink.string
|
||||||
alink.replaceWith(tstr)
|
alink.replaceWith(tstr)
|
||||||
return soup
|
return self.adeify_images(soup)
|
||||||
|
|
||||||
preprocess_regexps = [
|
preprocess_regexps = [
|
||||||
(re.compile(r'([0-9])%'), lambda m: m.group(1) + ' %'),
|
(re.compile(r'([0-9])%'), lambda m: m.group(1) + ' %'),
|
||||||
|
@ -118,6 +118,7 @@ sort_columns_at_startup = None
|
|||||||
# timestamp default if not set: dd MMM yyyy
|
# timestamp default if not set: dd MMM yyyy
|
||||||
gui_pubdate_display_format = 'MMM yyyy'
|
gui_pubdate_display_format = 'MMM yyyy'
|
||||||
gui_timestamp_display_format = 'dd MMM yyyy'
|
gui_timestamp_display_format = 'dd MMM yyyy'
|
||||||
|
gui_last_modified_display_format = 'dd MMM yyyy'
|
||||||
|
|
||||||
#: Control sorting of titles and series in the library display
|
#: Control sorting of titles and series in the library display
|
||||||
# Control title and series sorting in the library view. If set to
|
# Control title and series sorting in the library view. If set to
|
||||||
|
@ -460,7 +460,7 @@ class ITUNES(DriverBase):
|
|||||||
|
|
||||||
cached_books[this_book.path] = {
|
cached_books[this_book.path] = {
|
||||||
'title':book.Name,
|
'title':book.Name,
|
||||||
'author':book.artist().split(' & '),
|
'author':book.Artist.split(' & '),
|
||||||
'lib_book':library_books[this_book.path] if this_book.path in library_books else None,
|
'lib_book':library_books[this_book.path] if this_book.path in library_books else None,
|
||||||
'uuid': book.Composer,
|
'uuid': book.Composer,
|
||||||
'format': 'pdf' if book.KindAsString.startswith('PDF') else 'epub'
|
'format': 'pdf' if book.KindAsString.startswith('PDF') else 'epub'
|
||||||
|
@ -222,7 +222,7 @@ class SaveWorker(Thread):
|
|||||||
if isbytestring(fpath):
|
if isbytestring(fpath):
|
||||||
fpath = fpath.decode(filesystem_encoding)
|
fpath = fpath.decode(filesystem_encoding)
|
||||||
formats[fmt.lower()] = fpath
|
formats[fmt.lower()] = fpath
|
||||||
data[i] = [opf, cpath, formats]
|
data[i] = [opf, cpath, formats, mi.last_modified.isoformat()]
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -16,6 +16,7 @@ from calibre import CurrentDir
|
|||||||
from calibre.ebooks.pdb.formatreader import FormatReader
|
from calibre.ebooks.pdb.formatreader import FormatReader
|
||||||
from calibre.ptempfile import TemporaryFile
|
from calibre.ptempfile import TemporaryFile
|
||||||
from calibre.utils.magick import Image, create_canvas
|
from calibre.utils.magick import Image, create_canvas
|
||||||
|
from calibre.ebooks.compression.palmdoc import decompress_doc
|
||||||
|
|
||||||
DATATYPE_PHTML = 0
|
DATATYPE_PHTML = 0
|
||||||
DATATYPE_PHTML_COMPRESSED = 1
|
DATATYPE_PHTML_COMPRESSED = 1
|
||||||
|
@ -97,18 +97,25 @@ class RatingDelegate(QStyledItemDelegate): # {{{
|
|||||||
|
|
||||||
class DateDelegate(QStyledItemDelegate): # {{{
|
class DateDelegate(QStyledItemDelegate): # {{{
|
||||||
|
|
||||||
|
def __init__(self, parent, tweak_name='gui_timestamp_display_format',
|
||||||
|
default_format='dd MMM yyyy', editor_format='dd MMM yyyy'):
|
||||||
|
QStyledItemDelegate.__init__(self, parent)
|
||||||
|
self.tweak_name = tweak_name
|
||||||
|
self.default_format = default_format
|
||||||
|
self.editor_format = editor_format
|
||||||
|
|
||||||
def displayText(self, val, locale):
|
def displayText(self, val, locale):
|
||||||
d = val.toDate()
|
d = val.toDate()
|
||||||
if d <= UNDEFINED_QDATE:
|
if d <= UNDEFINED_QDATE:
|
||||||
return ''
|
return ''
|
||||||
format = tweaks['gui_timestamp_display_format']
|
format = tweaks[self.tweak_name]
|
||||||
if format is None:
|
if format is None:
|
||||||
format = 'dd MMM yyyy'
|
format = self.default_format
|
||||||
return format_date(d.toPyDate(), format)
|
return format_date(d.toPyDate(), format)
|
||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
qde = QStyledItemDelegate.createEditor(self, parent, option, index)
|
qde = QStyledItemDelegate.createEditor(self, parent, option, index)
|
||||||
qde.setDisplayFormat('dd MMM yyyy')
|
qde.setDisplayFormat(self.editor_format)
|
||||||
qde.setMinimumDate(UNDEFINED_QDATE)
|
qde.setMinimumDate(UNDEFINED_QDATE)
|
||||||
qde.setSpecialValueText(_('Undefined'))
|
qde.setSpecialValueText(_('Undefined'))
|
||||||
qde.setCalendarPopup(True)
|
qde.setCalendarPopup(True)
|
||||||
|
@ -70,6 +70,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
'publisher' : _("Publisher"),
|
'publisher' : _("Publisher"),
|
||||||
'tags' : _("Tags"),
|
'tags' : _("Tags"),
|
||||||
'series' : _("Series"),
|
'series' : _("Series"),
|
||||||
|
'last_modified' : _('Modified'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, parent=None, buffer=40):
|
def __init__(self, parent=None, buffer=40):
|
||||||
@ -620,6 +621,8 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
idx=self.db.field_metadata['timestamp']['rec_index']),
|
idx=self.db.field_metadata['timestamp']['rec_index']),
|
||||||
'pubdate' : functools.partial(datetime_type,
|
'pubdate' : functools.partial(datetime_type,
|
||||||
idx=self.db.field_metadata['pubdate']['rec_index']),
|
idx=self.db.field_metadata['pubdate']['rec_index']),
|
||||||
|
'last_modified': functools.partial(datetime_type,
|
||||||
|
idx=self.db.field_metadata['last_modified']['rec_index']),
|
||||||
'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,
|
||||||
|
@ -76,6 +76,8 @@ class BooksView(QTableView): # {{{
|
|||||||
self.rating_delegate = RatingDelegate(self)
|
self.rating_delegate = RatingDelegate(self)
|
||||||
self.timestamp_delegate = DateDelegate(self)
|
self.timestamp_delegate = DateDelegate(self)
|
||||||
self.pubdate_delegate = PubDateDelegate(self)
|
self.pubdate_delegate = PubDateDelegate(self)
|
||||||
|
self.last_modified_delegate = DateDelegate(self,
|
||||||
|
tweak_name='gui_last_modified_display_format')
|
||||||
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.cc_names_delegate = CompleteDelegate(self, '&', 'all_custom', True)
|
||||||
@ -296,6 +298,7 @@ class BooksView(QTableView): # {{{
|
|||||||
state = {}
|
state = {}
|
||||||
state['hidden_columns'] = [cm[i] for i in range(h.count())
|
state['hidden_columns'] = [cm[i] for i in range(h.count())
|
||||||
if h.isSectionHidden(i) and cm[i] != 'ondevice']
|
if h.isSectionHidden(i) and cm[i] != 'ondevice']
|
||||||
|
state['last_modified_injected'] = True
|
||||||
state['sort_history'] = \
|
state['sort_history'] = \
|
||||||
self.cleanup_sort_history(self.model().sort_history)
|
self.cleanup_sort_history(self.model().sort_history)
|
||||||
state['column_positions'] = {}
|
state['column_positions'] = {}
|
||||||
@ -380,7 +383,7 @@ class BooksView(QTableView): # {{{
|
|||||||
|
|
||||||
def get_default_state(self):
|
def get_default_state(self):
|
||||||
old_state = {
|
old_state = {
|
||||||
'hidden_columns': [],
|
'hidden_columns': ['last_modified'],
|
||||||
'sort_history':[DEFAULT_SORT],
|
'sort_history':[DEFAULT_SORT],
|
||||||
'column_positions': {},
|
'column_positions': {},
|
||||||
'column_sizes': {},
|
'column_sizes': {},
|
||||||
@ -388,6 +391,7 @@ class BooksView(QTableView): # {{{
|
|||||||
'size':'center',
|
'size':'center',
|
||||||
'timestamp':'center',
|
'timestamp':'center',
|
||||||
'pubdate':'center'},
|
'pubdate':'center'},
|
||||||
|
'last_modified_injected': True,
|
||||||
}
|
}
|
||||||
h = self.column_header
|
h = self.column_header
|
||||||
cm = self.column_map
|
cm = self.column_map
|
||||||
@ -398,7 +402,7 @@ class BooksView(QTableView): # {{{
|
|||||||
old_state['column_sizes'][name] = \
|
old_state['column_sizes'][name] = \
|
||||||
min(350, max(self.sizeHintForColumn(i),
|
min(350, max(self.sizeHintForColumn(i),
|
||||||
h.sectionSizeHint(i)))
|
h.sectionSizeHint(i)))
|
||||||
if name == 'timestamp':
|
if name in ('timestamp', 'last_modified'):
|
||||||
old_state['column_sizes'][name] += 12
|
old_state['column_sizes'][name] += 12
|
||||||
return old_state
|
return old_state
|
||||||
|
|
||||||
@ -418,6 +422,13 @@ class BooksView(QTableView): # {{{
|
|||||||
pass
|
pass
|
||||||
if ans is not None:
|
if ans is not None:
|
||||||
db.prefs[name] = ans
|
db.prefs[name] = ans
|
||||||
|
else:
|
||||||
|
if not ans.get('last_modified_injected', False):
|
||||||
|
ans['last_modified_injected'] = True
|
||||||
|
hc = ans.get('hidden_columns', [])
|
||||||
|
if 'last_modified' not in hc:
|
||||||
|
hc.append('last_modified')
|
||||||
|
db.prefs[name] = ans
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
@ -459,7 +470,8 @@ class BooksView(QTableView): # {{{
|
|||||||
def database_changed(self, db):
|
def database_changed(self, db):
|
||||||
for i in range(self.model().columnCount(None)):
|
for i in range(self.model().columnCount(None)):
|
||||||
if self.itemDelegateForColumn(i) in (self.rating_delegate,
|
if self.itemDelegateForColumn(i) in (self.rating_delegate,
|
||||||
self.timestamp_delegate, self.pubdate_delegate):
|
self.timestamp_delegate, self.pubdate_delegate,
|
||||||
|
self.last_modified_delegate):
|
||||||
self.setItemDelegateForColumn(i, self.itemDelegate())
|
self.setItemDelegateForColumn(i, self.itemDelegate())
|
||||||
|
|
||||||
cm = self.column_map
|
cm = self.column_map
|
||||||
|
@ -63,7 +63,7 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
self.shortcuts.linkActivated.connect(self.shortcut_activated)
|
self.shortcuts.linkActivated.connect(self.shortcut_activated)
|
||||||
text = '<p>'+_('Quick create:')
|
text = '<p>'+_('Quick create:')
|
||||||
for col, name in [('isbn', _('ISBN')), ('formats', _('Formats')),
|
for col, name in [('isbn', _('ISBN')), ('formats', _('Formats')),
|
||||||
('last_modified', _('Modified Date')), ('yesno', _('Yes/No')),
|
('yesno', _('Yes/No')),
|
||||||
('tags', _('Tags')), ('series', _('Series')), ('rating',
|
('tags', _('Tags')), ('series', _('Series')), ('rating',
|
||||||
_('Rating')), ('people', _("People's names"))]:
|
_('Rating')), ('people', _("People's names"))]:
|
||||||
text += ' <a href="col:%s">%s</a>,'%(col, name)
|
text += ' <a href="col:%s">%s</a>,'%(col, name)
|
||||||
@ -150,7 +150,6 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
'tags': _('My Tags'),
|
'tags': _('My Tags'),
|
||||||
'series': _('My Series'),
|
'series': _('My Series'),
|
||||||
'rating': _('My Rating'),
|
'rating': _('My Rating'),
|
||||||
'last_modified':_('Modified Date'),
|
|
||||||
'people': _('People')}[which])
|
'people': _('People')}[which])
|
||||||
self.is_names.setChecked(which == 'people')
|
self.is_names.setChecked(which == 'people')
|
||||||
if self.composite_box.isVisible():
|
if self.composite_box.isVisible():
|
||||||
@ -158,9 +157,8 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
{
|
{
|
||||||
'isbn': '{identifiers:select(isbn)}',
|
'isbn': '{identifiers:select(isbn)}',
|
||||||
'formats': '{formats}',
|
'formats': '{formats}',
|
||||||
'last_modified':'''{last_modified:'format_date($, "dd MMM yyyy")'}'''
|
|
||||||
}[which])
|
}[which])
|
||||||
self.composite_sort_by.setCurrentIndex(2 if which == 'last_modified' else 0)
|
self.composite_sort_by.setCurrentIndex(0)
|
||||||
|
|
||||||
def datatype_changed(self, *args):
|
def datatype_changed(self, *args):
|
||||||
try:
|
try:
|
||||||
|
@ -17,6 +17,7 @@ from calibre.ebooks.metadata.opf2 import metadata_to_opf
|
|||||||
from calibre.constants import preferred_encoding
|
from calibre.constants import preferred_encoding
|
||||||
from calibre.ebooks.metadata import fmt_sidx
|
from calibre.ebooks.metadata import fmt_sidx
|
||||||
from calibre.ebooks.metadata import title_sort
|
from calibre.ebooks.metadata import title_sort
|
||||||
|
from calibre.utils.date import parse_date
|
||||||
from calibre import strftime, prints, sanitize_file_name_unicode
|
from calibre import strftime, prints, sanitize_file_name_unicode
|
||||||
|
|
||||||
plugboard_any_device_value = 'any device'
|
plugboard_any_device_value = 'any device'
|
||||||
@ -42,6 +43,8 @@ FORMAT_ARG_DESCS = dict(
|
|||||||
publisher=_('The publisher'),
|
publisher=_('The publisher'),
|
||||||
timestamp=_('The date'),
|
timestamp=_('The date'),
|
||||||
pubdate=_('The published date'),
|
pubdate=_('The published date'),
|
||||||
|
last_modified=_('The date when the metadata for this book record'
|
||||||
|
' was last modified'),
|
||||||
id=_('The calibre internal id')
|
id=_('The calibre internal id')
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -191,6 +194,9 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
|||||||
format_args['timestamp'] = strftime(timefmt, mi.timestamp.timetuple())
|
format_args['timestamp'] = strftime(timefmt, mi.timestamp.timetuple())
|
||||||
if hasattr(mi.pubdate, 'timetuple'):
|
if hasattr(mi.pubdate, 'timetuple'):
|
||||||
format_args['pubdate'] = strftime(timefmt, mi.pubdate.timetuple())
|
format_args['pubdate'] = strftime(timefmt, mi.pubdate.timetuple())
|
||||||
|
if hasattr(mi, 'last_modified') and hasattr(mi.last_modified, 'timetuple'):
|
||||||
|
format_args['last_modified'] = strftime(timefmt, mi.last_modified.timetuple())
|
||||||
|
|
||||||
format_args['id'] = str(id)
|
format_args['id'] = str(id)
|
||||||
# Now format the custom fields
|
# Now format the custom fields
|
||||||
custom_metadata = mi.get_all_user_metadata(make_copy=False)
|
custom_metadata = mi.get_all_user_metadata(make_copy=False)
|
||||||
@ -373,10 +379,14 @@ def save_serialized_to_disk(ids, data, plugboards, root, opts, callback):
|
|||||||
root, opts, length = _sanitize_args(root, opts)
|
root, opts, length = _sanitize_args(root, opts)
|
||||||
failures = []
|
failures = []
|
||||||
for x in ids:
|
for x in ids:
|
||||||
opf, cover, format_map = data[x]
|
opf, cover, format_map, last_modified = data[x]
|
||||||
if isinstance(opf, unicode):
|
if isinstance(opf, unicode):
|
||||||
opf = opf.encode('utf-8')
|
opf = opf.encode('utf-8')
|
||||||
mi = OPF(cStringIO.StringIO(opf)).to_book_metadata()
|
mi = OPF(cStringIO.StringIO(opf)).to_book_metadata()
|
||||||
|
try:
|
||||||
|
mi.last_modified = parse_date(last_modified)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
tb = ''
|
tb = ''
|
||||||
try:
|
try:
|
||||||
failed, id, title = do_save_book_to_disk(x, mi, cover, plugboards,
|
failed, id, title = do_save_book_to_disk(x, mi, cover, plugboards,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user