mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
...
This commit is contained in:
commit
162a09a948
@ -292,7 +292,7 @@ class iPadOutput(OutputProfile):
|
|||||||
.touchscreen_navbar td {
|
.touchscreen_navbar td {
|
||||||
background:#fff;
|
background:#fff;
|
||||||
font-family:Helvetica;
|
font-family:Helvetica;
|
||||||
font-size:80%;
|
font-size:90%;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
}
|
}
|
||||||
@ -309,6 +309,14 @@ class iPadOutput(OutputProfile):
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Index formatting */
|
||||||
|
.publish_date {
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
border-bottom:1em solid white;
|
||||||
|
border-top:1px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
/* Feed summary formatting */
|
/* Feed summary formatting */
|
||||||
.feed_title {
|
.feed_title {
|
||||||
|
@ -18,6 +18,7 @@ from calibre.ebooks.metadata.epub import set_metadata
|
|||||||
from calibre.library.server.utils import strftime
|
from calibre.library.server.utils import strftime
|
||||||
from calibre.utils.config import config_dir
|
from calibre.utils.config import config_dir
|
||||||
from calibre.utils.date import isoformat, now, parse_date
|
from calibre.utils.date import isoformat, now, parse_date
|
||||||
|
from calibre.utils.localization import get_lang
|
||||||
from calibre.utils.logging import Log
|
from calibre.utils.logging import Log
|
||||||
from calibre.utils.zipfile import ZipFile
|
from calibre.utils.zipfile import ZipFile
|
||||||
|
|
||||||
@ -93,10 +94,15 @@ class ITUNES(DriverBase):
|
|||||||
|
|
||||||
|
|
||||||
# Product IDs:
|
# Product IDs:
|
||||||
# 0x1292:iPhone 3G
|
# 0x1291 iPod Touch
|
||||||
# 0x129a:iPad
|
# 0x1292 iPhone 3G
|
||||||
|
# 0x1293 iPod Touch 2G
|
||||||
|
# 0x1294 iPhone 3GS
|
||||||
|
# 0x1297 iPhone 4
|
||||||
|
# 0x1299 iPod Touch 3G
|
||||||
|
# 0x129a iPad
|
||||||
VENDOR_ID = [0x05ac]
|
VENDOR_ID = [0x05ac]
|
||||||
PRODUCT_ID = [0x129a]
|
PRODUCT_ID = [0x1292,0x1293,0x1294,0x1297,0x1299,0x129a]
|
||||||
BCD = [0x01]
|
BCD = [0x01]
|
||||||
|
|
||||||
# iTunes enumerations
|
# iTunes enumerations
|
||||||
@ -528,7 +534,7 @@ class ITUNES(DriverBase):
|
|||||||
cw.opt_save_template.setVisible(False)
|
cw.opt_save_template.setVisible(False)
|
||||||
cw.label.setVisible(False)
|
cw.label.setVisible(False)
|
||||||
# Repurpose the checkbox
|
# Repurpose the checkbox
|
||||||
cw.opt_read_metadata.setText(_("Use Series as Genre in iTunes/iBooks"))
|
cw.opt_read_metadata.setText(_("Use Series as Category in iTunes/iBooks"))
|
||||||
return cw
|
return cw
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
def delete_books(self, paths, end_session=True):
|
||||||
@ -837,6 +843,7 @@ class ITUNES(DriverBase):
|
|||||||
self.log.info("ITUNES.upload_books()")
|
self.log.info("ITUNES.upload_books()")
|
||||||
self._dump_files(files, header='upload_books()',indent=2)
|
self._dump_files(files, header='upload_books()',indent=2)
|
||||||
self._dump_update_list(header='upload_books()',indent=2)
|
self._dump_update_list(header='upload_books()',indent=2)
|
||||||
|
#self.log.info(" self.settings().format_map: %s" % self.settings().format_map)
|
||||||
|
|
||||||
if isosx:
|
if isosx:
|
||||||
for (i,file) in enumerate(files):
|
for (i,file) in enumerate(files):
|
||||||
@ -1201,13 +1208,13 @@ class ITUNES(DriverBase):
|
|||||||
try:
|
try:
|
||||||
this_book.datetime = parse_date(str(lb_added.date_added())).timetuple()
|
this_book.datetime = parse_date(str(lb_added.date_added())).timetuple()
|
||||||
except:
|
except:
|
||||||
pass
|
this_book.datetime = time.gmtime()
|
||||||
elif db_added:
|
elif db_added:
|
||||||
this_book.size = self._get_device_book_size(fpath, db_added.size())
|
this_book.size = self._get_device_book_size(fpath, db_added.size())
|
||||||
try:
|
try:
|
||||||
this_book.datetime = parse_date(str(db_added.date_added())).timetuple()
|
this_book.datetime = parse_date(str(db_added.date_added())).timetuple()
|
||||||
except:
|
except:
|
||||||
pass
|
this_book.datetime = time.gmtime()
|
||||||
|
|
||||||
elif iswindows:
|
elif iswindows:
|
||||||
if lb_added:
|
if lb_added:
|
||||||
@ -1215,13 +1222,13 @@ class ITUNES(DriverBase):
|
|||||||
try:
|
try:
|
||||||
this_book.datetime = parse_date(str(lb_added.DateAdded)).timetuple()
|
this_book.datetime = parse_date(str(lb_added.DateAdded)).timetuple()
|
||||||
except:
|
except:
|
||||||
pass
|
this_book.datetime = time.gmtime()
|
||||||
elif db_added:
|
elif db_added:
|
||||||
this_book.size = self._get_device_book_size(fpath, db_added.Size)
|
this_book.size = self._get_device_book_size(fpath, db_added.Size)
|
||||||
try:
|
try:
|
||||||
this_book.datetime = parse_date(str(db_added.DateAdded)).timetuple()
|
this_book.datetime = parse_date(str(db_added.DateAdded)).timetuple()
|
||||||
except:
|
except:
|
||||||
pass
|
this_book.datetime = time.gmtime()
|
||||||
|
|
||||||
return this_book
|
return this_book
|
||||||
|
|
||||||
@ -1900,10 +1907,14 @@ class ITUNES(DriverBase):
|
|||||||
# Collect calibre orphans - remnants of recipe uploads
|
# Collect calibre orphans - remnants of recipe uploads
|
||||||
path = self.path_template % (book.name(), book.artist())
|
path = self.path_template % (book.name(), book.artist())
|
||||||
if str(book.description()).startswith(self.description_prefix):
|
if str(book.description()).startswith(self.description_prefix):
|
||||||
if book.location() == appscript.k.missing_value:
|
try:
|
||||||
library_orphans[path] = book
|
if book.location() == appscript.k.missing_value:
|
||||||
if False:
|
library_orphans[path] = book
|
||||||
self.log.info(" found iTunes PTF '%s' in Library|Books" % book.name())
|
if False:
|
||||||
|
self.log.info(" found iTunes PTF '%s' in Library|Books" % book.name())
|
||||||
|
except:
|
||||||
|
if DEBUG:
|
||||||
|
self.log.error(" iTunes returned an error returning .location() with %s" % book.name())
|
||||||
|
|
||||||
library_books[path] = book
|
library_books[path] = book
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
@ -2062,10 +2073,22 @@ class ITUNES(DriverBase):
|
|||||||
(self.iTunes.name(), self.iTunes.version(), self.initial_status,
|
(self.iTunes.name(), self.iTunes.version(), self.initial_status,
|
||||||
self.version[0],self.version[1],self.version[2]))
|
self.version[0],self.version[1],self.version[2]))
|
||||||
self.log.info(" iTunes_media: %s" % self.iTunes_media)
|
self.log.info(" iTunes_media: %s" % self.iTunes_media)
|
||||||
|
|
||||||
if iswindows:
|
if iswindows:
|
||||||
'''
|
'''
|
||||||
Launch iTunes if not already running
|
Launch iTunes if not already running
|
||||||
Assumes pythoncom wrapper
|
Assumes pythoncom wrapper
|
||||||
|
|
||||||
|
*** Current implementation doesn't handle UNC paths correctly,
|
||||||
|
and python has two incompatible methods to parse UNCs:
|
||||||
|
os.path.splitdrive() and os.path.splitunc()
|
||||||
|
need to use os.path.normpath on result of splitunc()
|
||||||
|
|
||||||
|
Once you have the //server/share, convert with os.path.normpath('//server/share')
|
||||||
|
os.path.splitdrive doesn't work as advertised, so use os.path.splitunc
|
||||||
|
os.path.splitunc("//server/share") returns ('//server/share','')
|
||||||
|
os.path.splitunc("C:/Documents") returns ('c:','/documents')
|
||||||
|
os.path.normpath("//server/share") returns "\\\\server\\share"
|
||||||
'''
|
'''
|
||||||
# Instantiate iTunes
|
# Instantiate iTunes
|
||||||
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
||||||
@ -2074,6 +2097,8 @@ class ITUNES(DriverBase):
|
|||||||
self.initial_status = 'launched'
|
self.initial_status = 'launched'
|
||||||
|
|
||||||
# Read the current storage path for iTunes media from the XML file
|
# Read the current storage path for iTunes media from the XML file
|
||||||
|
media_dir = ''
|
||||||
|
string = None
|
||||||
with open(self.iTunes.LibraryXMLPath, 'r') as xml:
|
with open(self.iTunes.LibraryXMLPath, 'r') as xml:
|
||||||
for line in xml:
|
for line in xml:
|
||||||
if line.strip().startswith('<key>Music Folder'):
|
if line.strip().startswith('<key>Music Folder'):
|
||||||
@ -2083,10 +2108,12 @@ class ITUNES(DriverBase):
|
|||||||
break
|
break
|
||||||
if os.path.exists(media_dir):
|
if os.path.exists(media_dir):
|
||||||
self.iTunes_media = media_dir
|
self.iTunes_media = media_dir
|
||||||
else:
|
elif hasattr(string,'parent'):
|
||||||
self.log.error(" could not extract valid iTunes.media_dir from %s" % self.iTunes.LibraryXMLPath)
|
self.log.error(" could not extract valid iTunes.media_dir from %s" % self.iTunes.LibraryXMLPath)
|
||||||
self.log.error(" %s" % string.parent.prettify())
|
self.log.error(" %s" % string.parent.prettify())
|
||||||
self.log.error(" '%s' not found" % media_dir)
|
self.log.error(" '%s' not found" % media_dir)
|
||||||
|
else:
|
||||||
|
self.log.error(" no media dir found: string: %s" % string)
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" %s %s" % (__appname__, __version__))
|
self.log.info(" %s %s" % (__appname__, __version__))
|
||||||
@ -2248,8 +2275,8 @@ class ITUNES(DriverBase):
|
|||||||
path = book.Location
|
path = book.Location
|
||||||
|
|
||||||
if book:
|
if book:
|
||||||
storage_path = os.path.split(path)
|
if self.iTunes_media and path.startswith(self.iTunes_media):
|
||||||
if path.startswith(self.iTunes_media):
|
storage_path = os.path.split(path)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" removing '%s' at %s" %
|
self.log.info(" removing '%s' at %s" %
|
||||||
(cached_book['title'], path))
|
(cached_book['title'], path))
|
||||||
@ -2293,24 +2320,27 @@ class ITUNES(DriverBase):
|
|||||||
|
|
||||||
# Touch existing calibre timestamp
|
# Touch existing calibre timestamp
|
||||||
md = soup.find('metadata')
|
md = soup.find('metadata')
|
||||||
ts = md.find('meta',attrs={'name':'calibre:timestamp'})
|
if md:
|
||||||
if ts:
|
ts = md.find('meta',attrs={'name':'calibre:timestamp'})
|
||||||
timestamp = ts['content']
|
if ts:
|
||||||
old_ts = parse_date(timestamp)
|
timestamp = ts['content']
|
||||||
metadata.timestamp = datetime.datetime(old_ts.year, old_ts.month, old_ts.day, old_ts.hour,
|
old_ts = parse_date(timestamp)
|
||||||
old_ts.minute, old_ts.second, old_ts.microsecond+1, old_ts.tzinfo)
|
metadata.timestamp = datetime.datetime(old_ts.year, old_ts.month, old_ts.day, old_ts.hour,
|
||||||
|
old_ts.minute, old_ts.second, old_ts.microsecond+1, old_ts.tzinfo)
|
||||||
|
else:
|
||||||
|
metadata.timestamp = isoformat(now())
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info(" add timestamp: %s" % metadata.timestamp)
|
||||||
else:
|
else:
|
||||||
metadata.timestamp = isoformat(now())
|
metadata.timestamp = isoformat(now())
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
|
self.log.warning(" missing <metadata> block in OPF file")
|
||||||
self.log.info(" add timestamp: %s" % metadata.timestamp)
|
self.log.info(" add timestamp: %s" % metadata.timestamp)
|
||||||
|
|
||||||
# Fix the language declaration for iBooks 1.1
|
# Force the language declaration for iBooks 1.1
|
||||||
patched_language = 'en-US'
|
metadata.language = get_lang()
|
||||||
language = md.find('dc:language')
|
if DEBUG:
|
||||||
if language:
|
self.log.info(" rewriting language: <dc:language>%s</dc:language>" % metadata.language)
|
||||||
self.log.info(" changing <dc:language> from '%s' to '%s'" %
|
|
||||||
(language.renderContents(),patched_language))
|
|
||||||
metadata.language = patched_language
|
|
||||||
|
|
||||||
zf_opf.close()
|
zf_opf.close()
|
||||||
|
|
||||||
@ -2447,7 +2477,8 @@ class ITUNES(DriverBase):
|
|||||||
|
|
||||||
elif metadata.tags:
|
elif metadata.tags:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" using Tag as Genre")
|
self.log.info(" %susing Tag as Genre" %
|
||||||
|
"no Series name available, " if self.settings().read_metadata else '')
|
||||||
for tag in metadata.tags:
|
for tag in metadata.tags:
|
||||||
if self._is_alpha(tag[0]):
|
if self._is_alpha(tag[0]):
|
||||||
if lb_added:
|
if lb_added:
|
||||||
@ -2589,8 +2620,6 @@ class BookList(list):
|
|||||||
class Book(MetaInformation):
|
class Book(MetaInformation):
|
||||||
'''
|
'''
|
||||||
A simple class describing a book in the iTunes Books Library.
|
A simple class describing a book in the iTunes Books Library.
|
||||||
Q's:
|
|
||||||
- Should thumbnail come from calibre if available?
|
|
||||||
- See ebooks.metadata.__init__ for all fields
|
- See ebooks.metadata.__init__ for all fields
|
||||||
'''
|
'''
|
||||||
def __init__(self,title,author):
|
def __init__(self,title,author):
|
||||||
|
@ -8,7 +8,7 @@ import copy
|
|||||||
|
|
||||||
from lxml import html, etree
|
from lxml import html, etree
|
||||||
from lxml.html.builder import HTML, HEAD, TITLE, STYLE, DIV, BODY, \
|
from lxml.html.builder import HTML, HEAD, TITLE, STYLE, DIV, BODY, \
|
||||||
STRONG, EM, BR, SPAN, A, HR, UL, LI, H2, IMG, P as PT, \
|
STRONG, EM, BR, SPAN, A, HR, UL, LI, H2, H3, IMG, P as PT, \
|
||||||
TABLE, TD, TR
|
TABLE, TD, TR
|
||||||
|
|
||||||
from calibre import preferred_encoding, strftime, isbytestring
|
from calibre import preferred_encoding, strftime, isbytestring
|
||||||
@ -230,9 +230,8 @@ class TouchscreenIndexTemplate(Template):
|
|||||||
toc.append(tr)
|
toc.append(tr)
|
||||||
div = DIV(
|
div = DIV(
|
||||||
masthead_p,
|
masthead_p,
|
||||||
PT(date, style='text-align:center'),
|
H3(CLASS('publish_date'),date),
|
||||||
#DIV(style="border-color:gray;border-top-style:solid;border-width:thin"),
|
DIV(CLASS('divider')),
|
||||||
DIV(style="border-top:1px solid gray;border-bottom:1em solid white"),
|
|
||||||
toc)
|
toc)
|
||||||
self.root = HTML(head, BODY(div))
|
self.root = HTML(head, BODY(div))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user