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
3e726341da
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 160 KiB |
Binary file not shown.
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 396 KiB |
BIN
resources/tracer.epub
Normal file
BIN
resources/tracer.epub
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@ import os, re
|
|||||||
from mimetypes import guess_type as guess_mimetype
|
from mimetypes import guess_type as guess_mimetype
|
||||||
|
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString
|
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString
|
||||||
|
from calibre.constants import iswindows
|
||||||
from calibre.utils.chm.chm import CHMFile
|
from calibre.utils.chm.chm import CHMFile
|
||||||
from calibre.utils.chm.chmlib import (
|
from calibre.utils.chm.chmlib import (
|
||||||
CHM_RESOLVE_SUCCESS, CHM_ENUMERATE_NORMAL,
|
CHM_RESOLVE_SUCCESS, CHM_ENUMERATE_NORMAL,
|
||||||
@ -135,10 +135,16 @@ class CHMReader(CHMFile):
|
|||||||
if lpath.find(';') != -1:
|
if lpath.find(';') != -1:
|
||||||
# fix file names with ";<junk>" at the end, see _reformat()
|
# fix file names with ";<junk>" at the end, see _reformat()
|
||||||
lpath = lpath.split(';')[0]
|
lpath = lpath.split(';')[0]
|
||||||
|
try:
|
||||||
with open(lpath, 'wb') as f:
|
with open(lpath, 'wb') as f:
|
||||||
if guess_mimetype(path)[0] == ('text/html'):
|
if guess_mimetype(path)[0] == ('text/html'):
|
||||||
data = self._reformat(data)
|
data = self._reformat(data)
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
except:
|
||||||
|
if iswindows and len(lpath) > 250:
|
||||||
|
self.log.warn('%r filename too long, skipping'%path)
|
||||||
|
continue
|
||||||
|
raise
|
||||||
self._extracted = True
|
self._extracted = True
|
||||||
files = os.listdir(output_dir)
|
files = os.listdir(output_dir)
|
||||||
if self.hhc_path not in files:
|
if self.hhc_path not in files:
|
||||||
|
@ -260,7 +260,7 @@ class MetaInformation(object):
|
|||||||
setattr(self, x, getattr(mi, x, None))
|
setattr(self, x, getattr(mi, x, None))
|
||||||
|
|
||||||
def print_all_attributes(self):
|
def print_all_attributes(self):
|
||||||
for x in ('author', 'author_sort', 'title_sort', 'comments', 'category', 'publisher',
|
for x in ('title','author', 'author_sort', 'title_sort', 'comments', 'category', 'publisher',
|
||||||
'series', 'series_index', 'tags', 'rating', 'isbn', 'language',
|
'series', 'series_index', 'tags', 'rating', 'isbn', 'language',
|
||||||
'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover',
|
'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover',
|
||||||
'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc', 'pubdate',
|
'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc', 'pubdate',
|
||||||
|
@ -182,7 +182,7 @@ def get_metadata(stream, extract_cover=True):
|
|||||||
def get_quick_metadata(stream):
|
def get_quick_metadata(stream):
|
||||||
return get_metadata(stream, False)
|
return get_metadata(stream, False)
|
||||||
|
|
||||||
def set_metadata(stream, mi, apply_null=False):
|
def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
|
||||||
stream.seek(0)
|
stream.seek(0)
|
||||||
reader = OCFZipReader(stream, root=os.getcwdu())
|
reader = OCFZipReader(stream, root=os.getcwdu())
|
||||||
mi = MetaInformation(mi)
|
mi = MetaInformation(mi)
|
||||||
@ -196,6 +196,8 @@ def set_metadata(stream, mi, apply_null=False):
|
|||||||
reader.opf.tags = []
|
reader.opf.tags = []
|
||||||
if not getattr(mi, 'isbn', None):
|
if not getattr(mi, 'isbn', None):
|
||||||
reader.opf.isbn = None
|
reader.opf.isbn = None
|
||||||
|
if update_timestamp and mi.timestamp is not None:
|
||||||
|
reader.opf.timestamp = mi.timestamp
|
||||||
|
|
||||||
newopf = StringIO(reader.opf.render())
|
newopf = StringIO(reader.opf.render())
|
||||||
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf)
|
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf)
|
||||||
|
@ -689,14 +689,28 @@ class DeviceMixin(object): # {{{
|
|||||||
self.device_error_dialog.show()
|
self.device_error_dialog.show()
|
||||||
|
|
||||||
# Device connected {{{
|
# Device connected {{{
|
||||||
def device_detected(self, connected, is_folder_device):
|
|
||||||
'''
|
def set_device_menu_items_state(self, connected, is_folder_device):
|
||||||
Called when a device is connected to the computer.
|
|
||||||
'''
|
|
||||||
if connected:
|
if connected:
|
||||||
self._sync_menu.connect_to_folder_action.setEnabled(False)
|
self._sync_menu.connect_to_folder_action.setEnabled(False)
|
||||||
if is_folder_device:
|
if is_folder_device:
|
||||||
self._sync_menu.disconnect_from_folder_action.setEnabled(True)
|
self._sync_menu.disconnect_from_folder_action.setEnabled(True)
|
||||||
|
self._sync_menu.enable_device_actions(True,
|
||||||
|
self.device_manager.device.card_prefix(),
|
||||||
|
self.device_manager.device)
|
||||||
|
self.eject_action.setEnabled(True)
|
||||||
|
else:
|
||||||
|
self._sync_menu.connect_to_folder_action.setEnabled(True)
|
||||||
|
self._sync_menu.disconnect_from_folder_action.setEnabled(False)
|
||||||
|
self._sync_menu.enable_device_actions(False)
|
||||||
|
self.eject_action.setEnabled(False)
|
||||||
|
|
||||||
|
def device_detected(self, connected, is_folder_device):
|
||||||
|
'''
|
||||||
|
Called when a device is connected to the computer.
|
||||||
|
'''
|
||||||
|
self.set_device_menu_items_state(connected, is_folder_device)
|
||||||
|
if connected:
|
||||||
self.device_manager.get_device_information(\
|
self.device_manager.get_device_information(\
|
||||||
Dispatcher(self.info_read))
|
Dispatcher(self.info_read))
|
||||||
self.set_default_thumbnail(\
|
self.set_default_thumbnail(\
|
||||||
@ -705,17 +719,10 @@ class DeviceMixin(object): # {{{
|
|||||||
self.device_manager.device.__class__.get_gui_name()+\
|
self.device_manager.device.__class__.get_gui_name()+\
|
||||||
_(' detected.'), 3000)
|
_(' detected.'), 3000)
|
||||||
self.device_connected = 'device' if not is_folder_device else 'folder'
|
self.device_connected = 'device' if not is_folder_device else 'folder'
|
||||||
self._sync_menu.enable_device_actions(True,
|
|
||||||
self.device_manager.device.card_prefix(),
|
|
||||||
self.device_manager.device)
|
|
||||||
self.location_view.model().device_connected(self.device_manager.device)
|
self.location_view.model().device_connected(self.device_manager.device)
|
||||||
self.eject_action.setEnabled(True)
|
|
||||||
self.refresh_ondevice_info (device_connected = True, reset_only = True)
|
self.refresh_ondevice_info (device_connected = True, reset_only = True)
|
||||||
else:
|
else:
|
||||||
self._sync_menu.connect_to_folder_action.setEnabled(True)
|
|
||||||
self._sync_menu.disconnect_from_folder_action.setEnabled(False)
|
|
||||||
self.device_connected = None
|
self.device_connected = None
|
||||||
self._sync_menu.enable_device_actions(False)
|
|
||||||
self.location_view.model().update_devices()
|
self.location_view.model().update_devices()
|
||||||
self.vanity.setText(self.vanity_template%\
|
self.vanity.setText(self.vanity_template%\
|
||||||
dict(version=self.latest_version, device=' '))
|
dict(version=self.latest_version, device=' '))
|
||||||
@ -723,7 +730,6 @@ class DeviceMixin(object): # {{{
|
|||||||
if self.current_view() != self.library_view:
|
if self.current_view() != self.library_view:
|
||||||
self.book_details.reset_info()
|
self.book_details.reset_info()
|
||||||
self.location_view.setCurrentIndex(self.location_view.model().index(0))
|
self.location_view.setCurrentIndex(self.location_view.model().index(0))
|
||||||
self.eject_action.setEnabled(False)
|
|
||||||
self.refresh_ondevice_info (device_connected = False)
|
self.refresh_ondevice_info (device_connected = False)
|
||||||
|
|
||||||
def info_read(self, job):
|
def info_read(self, job):
|
||||||
|
@ -84,12 +84,12 @@ class DownloadMetadata(Thread):
|
|||||||
if mi.isbn:
|
if mi.isbn:
|
||||||
args['isbn'] = mi.isbn
|
args['isbn'] = mi.isbn
|
||||||
else:
|
else:
|
||||||
if not mi.title:
|
if not mi.title or mi.title == _('Unknown'):
|
||||||
self.failures[id] = \
|
self.failures[id] = \
|
||||||
(str(id), _('Book has neither title nor ISBN'))
|
(str(id), _('Book has neither title nor ISBN'))
|
||||||
continue
|
continue
|
||||||
args['title'] = mi.title
|
args['title'] = mi.title
|
||||||
if mi.authors:
|
if mi.authors and mi.authors[0] != _('Unknown'):
|
||||||
args['author'] = mi.authors[0]
|
args['author'] = mi.authors[0]
|
||||||
if self.key:
|
if self.key:
|
||||||
args['isbndb_key'] = self.key
|
args['isbndb_key'] = self.key
|
||||||
|
@ -410,6 +410,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
|
|||||||
self.tags_view.set_new_model() # in case columns changed
|
self.tags_view.set_new_model() # in case columns changed
|
||||||
self.tags_view.recount()
|
self.tags_view.recount()
|
||||||
self.create_device_menu()
|
self.create_device_menu()
|
||||||
|
self.set_device_menu_items_state(bool(self.device_connected),
|
||||||
|
self.device_connected == 'folder')
|
||||||
|
|
||||||
if not patheq(self.library_path, d.database_location):
|
if not patheq(self.library_path, d.database_location):
|
||||||
newloc = d.database_location
|
newloc = d.database_location
|
||||||
|
@ -788,6 +788,7 @@ class BasicNewsRecipe(Recipe):
|
|||||||
}
|
}
|
||||||
|
|
||||||
.summary_byline {
|
.summary_byline {
|
||||||
|
text-align:left;
|
||||||
font-family:monospace;
|
font-family:monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1139,12 +1140,6 @@ class BasicNewsRecipe(Recipe):
|
|||||||
mi = MetaInformation(self.short_title() + strftime(self.timefmt), [__appname__])
|
mi = MetaInformation(self.short_title() + strftime(self.timefmt), [__appname__])
|
||||||
mi.publisher = __appname__
|
mi.publisher = __appname__
|
||||||
mi.author_sort = __appname__
|
mi.author_sort = __appname__
|
||||||
if self.output_profile.name == 'iPad':
|
|
||||||
date_as_author = '%s, %s %s, %s' % (strftime('%A'), strftime('%B'), strftime('%d').lstrip('0'), strftime('%Y'))
|
|
||||||
mi = MetaInformation(self.short_title(), [date_as_author])
|
|
||||||
mi.publisher = __appname__
|
|
||||||
sort_author = re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', self.title).rstrip()
|
|
||||||
mi.author_sort = '%s %s' % (sort_author, strftime('%Y-%m-%d'))
|
|
||||||
mi.publication_type = 'periodical:'+self.publication_type
|
mi.publication_type = 'periodical:'+self.publication_type
|
||||||
mi.timestamp = nowf()
|
mi.timestamp = nowf()
|
||||||
mi.comments = self.description
|
mi.comments = self.description
|
||||||
|
Loading…
x
Reference in New Issue
Block a user