Cybook: Fixed reference to IDs on Windows

This commit is contained in:
John Schember 2009-01-06 19:12:17 -05:00
commit 1d451f4ee2
18 changed files with 268 additions and 118 deletions

View File

@ -16,6 +16,7 @@ def freeze():
from calibre.linux import entry_points from calibre.linux import entry_points
from calibre import walk from calibre import walk
from calibre.web.feeds.recipes import recipe_modules from calibre.web.feeds.recipes import recipe_modules
from calibre.ebooks.lrf.fonts import FONT_MAP
import calibre import calibre
@ -37,6 +38,7 @@ def freeze():
'/usr/lib/libxml2.so.2', '/usr/lib/libxml2.so.2',
'/usr/lib/libxslt.so.1', '/usr/lib/libxslt.so.1',
'/usr/lib/libxslt.so.1', '/usr/lib/libxslt.so.1',
'/usr/lib/libexslt.so.0',
'/usr/lib/libMagickWand.so', '/usr/lib/libMagickWand.so',
'/usr/lib/libMagickCore.so', '/usr/lib/libMagickCore.so',
] ]
@ -72,6 +74,7 @@ def freeze():
os.makedirs(DIST_DIR) os.makedirs(DIST_DIR)
includes = [x[0] for x in executables.values()] includes = [x[0] for x in executables.values()]
includes += ['calibre.ebooks.lrf.fonts.prs500.'+x for x in FONT_MAP.values()]
excludes = ['matplotlib', "Tkconstants", "Tkinter", "tcl", "_imagingtk", excludes = ['matplotlib', "Tkconstants", "Tkinter", "tcl", "_imagingtk",
"ImageTk", "FixTk", 'wx', 'PyQt4.QtAssistant', 'PyQt4.QtOpenGL.so', "ImageTk", "FixTk", 'wx', 'PyQt4.QtAssistant', 'PyQt4.QtOpenGL.so',

View File

@ -326,7 +326,7 @@ def main():
'genshi', 'calibre.web.feeds.recipes.*', 'genshi', 'calibre.web.feeds.recipes.*',
'calibre.ebooks.lrf.any.*', 'calibre.ebooks.lrf.feeds.*', 'calibre.ebooks.lrf.any.*', 'calibre.ebooks.lrf.feeds.*',
'keyword', 'codeop', 'pydoc', 'readline', 'keyword', 'codeop', 'pydoc', 'readline',
'BeautifulSoup' 'BeautifulSoup', 'calibre.ebooks.lrf.fonts.prs500.*',
], ],
'packages' : ['PIL', 'Authorization', 'lxml'], 'packages' : ['PIL', 'Authorization', 'lxml'],
'excludes' : ['IPython'], 'excludes' : ['IPython'],

View File

@ -176,6 +176,7 @@ def main(args=sys.argv):
'BeautifulSoup', 'pyreadline', 'BeautifulSoup', 'pyreadline',
'pydoc', 'IPython.Extensions.*', 'pydoc', 'IPython.Extensions.*',
'calibre.web.feeds.recipes.*', 'calibre.web.feeds.recipes.*',
'calibre.ebooks.lrf.fonts.prs500.*',
'PyQt4.QtWebKit', 'PyQt4.QtNetwork', 'PyQt4.QtWebKit', 'PyQt4.QtNetwork',
], ],
'packages' : ['PIL', 'lxml', 'cherrypy'], 'packages' : ['PIL', 'lxml', 'cherrypy'],

View File

@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
__appname__ = 'calibre' __appname__ = 'calibre'
__version__ = '0.4.125' __version__ = '0.4.126'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>" __author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
''' '''
Various run time constants. Various run time constants.

View File

@ -105,31 +105,44 @@ def reread_metadata_plugins():
for plugin in _initialized_plugins: for plugin in _initialized_plugins:
if isinstance(plugin, MetadataReaderPlugin): if isinstance(plugin, MetadataReaderPlugin):
for ft in plugin.file_types: for ft in plugin.file_types:
_metadata_readers[ft] = plugin if not _metadata_readers.has_key(ft):
_metadata_readers[ft] = []
_metadata_readers[ft].append(plugin)
elif isinstance(plugin, MetadataWriterPlugin): elif isinstance(plugin, MetadataWriterPlugin):
for ft in plugin.file_types: for ft in plugin.file_types:
_metadata_writers[ft] = plugin if not _metadata_writers.has_key(ft):
_metadata_writers[ft] = []
_metadata_writers[ft].append(plugin)
def get_file_type_metadata(stream, ftype): def get_file_type_metadata(stream, ftype):
mi = MetaInformation(None, None) mi = MetaInformation(None, None)
try: ftype = ftype.lower().strip()
plugin = _metadata_readers[ftype.lower().strip()] if _metadata_readers.has_key(ftype):
for plugin in _metadata_readers[ftype]:
if not is_disabled(plugin): if not is_disabled(plugin):
with plugin: with plugin:
try:
mi = plugin.get_metadata(stream, ftype.lower().strip()) mi = plugin.get_metadata(stream, ftype.lower().strip())
break
except: except:
pass continue
return mi return mi
def set_file_type_metadata(stream, mi, ftype): def set_file_type_metadata(stream, mi, ftype):
try: ftype = ftype.lower().strip()
plugin = _metadata_writers[ftype.lower().strip()] if _metadata_writers.has_key(ftype):
for plugin in _metadata_writers[ftype]:
if not is_disabled(plugin): if not is_disabled(plugin):
with plugin: with plugin:
try:
plugin.set_metadata(stream, mi, ftype.lower().strip()) plugin.set_metadata(stream, mi, ftype.lower().strip())
break
except: except:
traceback.print_exc() traceback.print_exc()
def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'): def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
occasion = {'import':_on_import, 'preprocess':_on_preprocess, occasion = {'import':_on_import, 'preprocess':_on_preprocess,
'postprocess':_on_postprocess}[occasion] 'postprocess':_on_postprocess}[occasion]

View File

@ -222,11 +222,11 @@ class CYBOOKG3(Device):
path = path.replace('card:', self._card_prefix[:-1]) path = path.replace('card:', self._card_prefix[:-1])
return path return path
@classmethod
def _windows_match_device(self, device_id): def windows_match_device(cls, device_id):
device_id = device_id.upper() device_id = device_id.upper()
if 'VEN_'+self.VENDOR_NAME in device_id and \ if 'VEN_'+cls.VENDOR_NAME in device_id and \
'PROD_'+self.PRODUCT_NAME in device_id: 'PROD_'+cls.PRODUCT_NAME in device_id:
return True return True
vid, pid = hex(cls.VENDOR_ID)[2:], hex(cls.PRODUCT_ID)[2:] vid, pid = hex(cls.VENDOR_ID)[2:], hex(cls.PRODUCT_ID)[2:]
@ -243,7 +243,7 @@ class CYBOOKG3(Device):
wmi = __import__('wmi', globals(), locals(), [], -1) wmi = __import__('wmi', globals(), locals(), [], -1)
c = wmi.WMI() c = wmi.WMI()
for drive in c.Win32_DiskDrive(): for drive in c.Win32_DiskDrive():
if self._windows_match_device(str(drive.PNPDeviceID)): if self.__class__.windows_match_device(str(drive.PNPDeviceID)):
if drive.Partitions == 0: if drive.Partitions == 0:
continue continue
try: try:

View File

@ -50,7 +50,8 @@ def get_font_path(name):
try: try:
font_mod = __import__('calibre.ebooks.lrf.fonts.prs500', {}, {}, font_mod = __import__('calibre.ebooks.lrf.fonts.prs500', {}, {},
[fname], -1) [fname], -1)
except ImportError: getattr(font_mod, fname)
except (ImportError, AttributeError):
font_mod = __import__('calibre.ebooks.lrf.fonts.liberation', {}, {}, font_mod = __import__('calibre.ebooks.lrf.fonts.liberation', {}, {},
[LIBERATION_FONT_MAP[name]], -1) [LIBERATION_FONT_MAP[name]], -1)
p = PersistentTemporaryFile('.ttf', 'font_') p = PersistentTemporaryFile('.ttf', 'font_')

View File

@ -245,7 +245,6 @@ class HTMLConverter(object, LoggingInterface):
self.override_css = {} self.override_css = {}
self.override_pcss = {} self.override_pcss = {}
self.table_render_job_server = None
if self._override_css is not None: if self._override_css is not None:
if os.access(self._override_css, os.R_OK): if os.access(self._override_css, os.R_OK):
@ -266,7 +265,6 @@ class HTMLConverter(object, LoggingInterface):
paths = [os.path.abspath(path) for path in paths] paths = [os.path.abspath(path) for path in paths]
paths = [path.decode(sys.getfilesystemencoding()) if not isinstance(path, unicode) else path for path in paths] paths = [path.decode(sys.getfilesystemencoding()) if not isinstance(path, unicode) else path for path in paths]
try:
while len(paths) > 0 and self.link_level <= self.link_levels: while len(paths) > 0 and self.link_level <= self.link_levels:
for path in paths: for path in paths:
if path in self.processed_files: if path in self.processed_files:
@ -298,9 +296,6 @@ class HTMLConverter(object, LoggingInterface):
if self.base_font_size > 0: if self.base_font_size > 0:
self.log_info('\tRationalizing font sizes...') self.log_info('\tRationalizing font sizes...')
self.book.rationalize_font_sizes(self.base_font_size) self.book.rationalize_font_sizes(self.base_font_size)
finally:
if self.table_render_job_server is not None:
self.table_render_job_server.killall()
def is_baen(self, soup): def is_baen(self, soup):
return bool(soup.find('meta', attrs={'name':'Publisher', return bool(soup.find('meta', attrs={'name':'Publisher',
@ -1732,15 +1727,11 @@ class HTMLConverter(object, LoggingInterface):
self.process_children(tag, tag_css, tag_pseudo_css) self.process_children(tag, tag_css, tag_pseudo_css)
elif tagname == 'table' and not self.ignore_tables and not self.in_table: elif tagname == 'table' and not self.ignore_tables and not self.in_table:
if self.render_tables_as_images: if self.render_tables_as_images:
if self.table_render_job_server is None:
from calibre.parallel import Server
self.table_render_job_server = Server(number_of_workers=1)
print 'Rendering table...' print 'Rendering table...'
from calibre.ebooks.lrf.html.table_as_image import render_table from calibre.ebooks.lrf.html.table_as_image import render_table
pheight = int(self.current_page.pageStyle.attrs['textheight']) pheight = int(self.current_page.pageStyle.attrs['textheight'])
pwidth = int(self.current_page.pageStyle.attrs['textwidth']) pwidth = int(self.current_page.pageStyle.attrs['textwidth'])
images = render_table(self.table_render_job_server, images = render_table(self.soup, tag, tag_css,
self.soup, tag, tag_css,
os.path.dirname(self.target_prefix), os.path.dirname(self.target_prefix),
pwidth, pheight, self.profile.dpi, pwidth, pheight, self.profile.dpi,
self.text_size_multiplier_for_rendered_tables) self.text_size_multiplier_for_rendered_tables)

View File

@ -6,14 +6,11 @@ __docformat__ = 'restructuredtext en'
''' '''
Render HTML tables as images. Render HTML tables as images.
''' '''
import os, tempfile, atexit, shutil, time import os, tempfile, atexit, shutil
from PyQt4.Qt import QUrl, QApplication, QSize, \ from PyQt4.Qt import QUrl, QApplication, QSize, QEventLoop, \
SIGNAL, QPainter, QImage, QObject, Qt SIGNAL, QPainter, QImage, QObject, Qt
from PyQt4.QtWebKit import QWebPage from PyQt4.QtWebKit import QWebPage
from calibre.parallel import ParallelJob
__app = None
class HTMLTableRenderer(QObject): class HTMLTableRenderer(QObject):
@ -27,13 +24,15 @@ class HTMLTableRenderer(QObject):
self.app = None self.app = None
self.width, self.height, self.dpi = width, height, dpi self.width, self.height, self.dpi = width, height, dpi
self.base_dir = base_dir self.base_dir = base_dir
self.images = []
self.tdir = tempfile.mkdtemp(prefix='calibre_render_table')
self.loop = QEventLoop()
self.page = QWebPage() self.page = QWebPage()
self.connect(self.page, SIGNAL('loadFinished(bool)'), self.render_html) self.connect(self.page, SIGNAL('loadFinished(bool)'), self.render_html)
self.page.mainFrame().setTextSizeMultiplier(factor) self.page.mainFrame().setTextSizeMultiplier(factor)
self.page.mainFrame().setHtml(html, self.page.mainFrame().setHtml(html,
QUrl('file:'+os.path.abspath(self.base_dir))) QUrl('file:'+os.path.abspath(self.base_dir)))
self.images = []
self.tdir = tempfile.mkdtemp(prefix='calibre_render_table')
def render_html(self, ok): def render_html(self, ok):
try: try:
@ -63,7 +62,7 @@ class HTMLTableRenderer(QObject):
finally: finally:
QApplication.quit() QApplication.quit()
def render_table(server, soup, table, css, base_dir, width, height, dpi, factor=1.0): def render_table(soup, table, css, base_dir, width, height, dpi, factor=1.0):
head = '' head = ''
for e in soup.findAll(['link', 'style']): for e in soup.findAll(['link', 'style']):
head += unicode(e)+'\n\n' head += unicode(e)+'\n\n'
@ -83,24 +82,13 @@ def render_table(server, soup, table, css, base_dir, width, height, dpi, factor=
</body> </body>
</html> </html>
'''%(head, width-10, style, unicode(table)) '''%(head, width-10, style, unicode(table))
job = ParallelJob('render_table', lambda j : j, None, images, tdir = do_render(html, base_dir, width, height, dpi, factor)
args=[html, base_dir, width, height, dpi, factor])
server.add_job(job)
while not job.has_run:
time.sleep(2)
if job.exception is not None:
print 'Failed to render table'
print job.exception
print job.traceback
images, tdir = job.result
atexit.register(shutil.rmtree, tdir) atexit.register(shutil.rmtree, tdir)
return images return images
def do_render(html, base_dir, width, height, dpi, factor): def do_render(html, base_dir, width, height, dpi, factor):
app = QApplication.instance() if QApplication.instance() is None:
if app is None: QApplication([])
app = QApplication([])
tr = HTMLTableRenderer(html, base_dir, width, height, dpi, factor) tr = HTMLTableRenderer(html, base_dir, width, height, dpi, factor)
app.exec_() tr.loop.exec_()
return tr.images, tr.tdir return tr.images, tr.tdir

View File

@ -600,6 +600,33 @@
<header>widgets.h</header> <header>widgets.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<tabstops>
<tabstop>title</tabstop>
<tabstop>swap_button</tabstop>
<tabstop>authors</tabstop>
<tabstop>author_sort</tabstop>
<tabstop>auto_author_sort</tabstop>
<tabstop>rating</tabstop>
<tabstop>publisher</tabstop>
<tabstop>tags</tabstop>
<tabstop>tag_editor_button</tabstop>
<tabstop>series</tabstop>
<tabstop>remove_series_button</tabstop>
<tabstop>series_index</tabstop>
<tabstop>isbn</tabstop>
<tabstop>comments</tabstop>
<tabstop>fetch_metadata_button</tabstop>
<tabstop>fetch_cover_button</tabstop>
<tabstop>password_button</tabstop>
<tabstop>cover_button</tabstop>
<tabstop>reset_cover</tabstop>
<tabstop>cover_path</tabstop>
<tabstop>add_format_button</tabstop>
<tabstop>button_set_cover</tabstop>
<tabstop>remove_format_button</tabstop>
<tabstop>formats</tabstop>
<tabstop>button_box</tabstop>
</tabstops>
<resources> <resources>
<include location="../images.qrc" /> <include location="../images.qrc" />
</resources> </resources>

View File

@ -1424,7 +1424,12 @@ in which you want to store your books files. Any existing books will be automati
self.memory_view.write_settings() self.memory_view.write_settings()
def quit(self, checked, restart=False): def quit(self, checked, restart=False):
if self.shutdown(): if not self.confirm_quit():
return
try:
self.shutdown()
except:
pass
self.restart_after_quit = restart self.restart_after_quit = restart
QApplication.instance().quit() QApplication.instance().quit()
@ -1457,22 +1462,26 @@ in which you want to store your books files. Any existing books will be automati
QDesktopServices.openUrl(QUrl.fromLocalFile(pt.name)) QDesktopServices.openUrl(QUrl.fromLocalFile(pt.name))
def shutdown(self): def confirm_quit(self):
if self.job_manager.has_jobs():
msg = _('There are active jobs. Are you sure you want to quit?') msg = _('There are active jobs. Are you sure you want to quit?')
if self.job_manager.has_device_jobs(): if self.job_manager.has_device_jobs():
msg = '<p>'+__appname__ + _(''' is communicating with the device!<br> msg = '<p>'+__appname__ + _(''' is communicating with the device!<br>
'Quitting may cause corruption on the device.<br> 'Quitting may cause corruption on the device.<br>
'Are you sure you want to quit?''')+'</p>' 'Are you sure you want to quit?''')+'</p>'
if self.job_manager.has_jobs():
d = QMessageBox(QMessageBox.Warning, _('WARNING: Active jobs'), msg, d = QMessageBox(QMessageBox.Warning, _('WARNING: Active jobs'), msg,
QMessageBox.Yes|QMessageBox.No, self) QMessageBox.Yes|QMessageBox.No, self)
d.setIconPixmap(QPixmap(':/images/dialog_warning.svg')) d.setIconPixmap(QPixmap(':/images/dialog_warning.svg'))
d.setDefaultButton(QMessageBox.No) d.setDefaultButton(QMessageBox.No)
if d.exec_() != QMessageBox.Yes: if d.exec_() != QMessageBox.Yes:
return False return False
return True
self.job_manager.terminate_all_jobs()
def shutdown(self):
self.write_settings() self.write_settings()
self.job_manager.terminate_all_jobs()
self.device_manager.keep_going = False self.device_manager.keep_going = False
self.cover_cache.stop() self.cover_cache.stop()
self.hide() self.hide()
@ -1498,7 +1507,11 @@ in which you want to store your books files. Any existing books will be automati
self.hide() self.hide()
e.ignore() e.ignore()
else: else:
if self.shutdown(): if self.confirm_quit():
try:
self.shutdown()
except:
pass
e.accept() e.accept()
else: else:
e.ignore() e.ignore()

View File

@ -13,7 +13,7 @@ from calibre.utils.config import prefs
from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog
from calibre.gui2.dialogs.epub import Config as EPUBConvert from calibre.gui2.dialogs.epub import Config as EPUBConvert
import calibre.gui2.dialogs.comicconf as ComicConf import calibre.gui2.dialogs.comicconf as ComicConf
from calibre.gui2 import warning_dialog, dynamic from calibre.gui2 import warning_dialog
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
from calibre.ebooks.lrf import preferred_source_formats as LRF_PREFERRED_SOURCE_FORMATS from calibre.ebooks.lrf import preferred_source_formats as LRF_PREFERRED_SOURCE_FORMATS
from calibre.ebooks.metadata.opf import OPFCreator from calibre.ebooks.metadata.opf import OPFCreator
@ -22,7 +22,9 @@ from calibre.ebooks.epub.from_any import SOURCE_FORMATS as EPUB_PREFERRED_SOURCE
def convert_single_epub(parent, db, comics, others): def convert_single_epub(parent, db, comics, others):
changed = False changed = False
jobs = [] jobs = []
for row in others: others_ids = [db.id(row) for row in others]
comics_ids = [db.id(row) for row in comics]
for row, row_id in zip(others, others_ids):
temp_files = [] temp_files = []
d = EPUBConvert(parent, db, row) d = EPUBConvert(parent, db, row)
if d.source_format is not None: if d.source_format is not None:
@ -44,10 +46,10 @@ def convert_single_epub(parent, db, comics, others):
opts.cover = d.cover_file.name opts.cover = d.cover_file.name
temp_files.extend([d.opf_file, pt, of]) temp_files.extend([d.opf_file, pt, of])
jobs.append(('any2epub', args, _('Convert book: ')+d.mi.title, jobs.append(('any2epub', args, _('Convert book: ')+d.mi.title,
'EPUB', db.id(row), temp_files)) 'EPUB', row_id, temp_files))
changed = True changed = True
for row in comics: for row, row_id in zip(comics, comics_ids):
mi = db.get_metadata(row) mi = db.get_metadata(row)
title = author = _('Unknown') title = author = _('Unknown')
if mi.title: if mi.title:
@ -76,7 +78,7 @@ def convert_single_epub(parent, db, comics, others):
args = [pt.name, opts] args = [pt.name, opts]
changed = True changed = True
jobs.append(('comic2epub', args, _('Convert comic: ')+opts.title, jobs.append(('comic2epub', args, _('Convert comic: ')+opts.title,
'EPUB', db.id(row), [pt, of])) 'EPUB', row_id, [pt, of]))
return jobs, changed return jobs, changed
@ -85,7 +87,9 @@ def convert_single_epub(parent, db, comics, others):
def convert_single_lrf(parent, db, comics, others): def convert_single_lrf(parent, db, comics, others):
changed = False changed = False
jobs = [] jobs = []
for row in others: others_ids = [db.id(row) for row in others]
comics_ids = [db.id(row) for row in comics]
for row, row_id in zip(others, others_ids):
temp_files = [] temp_files = []
d = LRFSingleDialog(parent, db, row) d = LRFSingleDialog(parent, db, row)
if d.selected_format: if d.selected_format:
@ -104,10 +108,10 @@ def convert_single_lrf(parent, db, comics, others):
temp_files.append(d.cover_file) temp_files.append(d.cover_file)
temp_files.extend([pt, of]) temp_files.extend([pt, of])
jobs.append(('any2lrf', [cmdline], _('Convert book: ')+d.title(), jobs.append(('any2lrf', [cmdline], _('Convert book: ')+d.title(),
'LRF', db.id(row), temp_files)) 'LRF', row_id, temp_files))
changed = True changed = True
for row in comics: for row, row_id in zip(comics, comics_ids):
mi = db.get_metadata(row) mi = db.get_metadata(row)
title = author = _('Unknown') title = author = _('Unknown')
if mi.title: if mi.title:
@ -138,7 +142,7 @@ def convert_single_lrf(parent, db, comics, others):
args = [pt.name, opts] args = [pt.name, opts]
changed = True changed = True
jobs.append(('comic2lrf', args, _('Convert comic: ')+opts.title, jobs.append(('comic2lrf', args, _('Convert comic: ')+opts.title,
'LRF', db.id(row), [pt, of])) 'LRF', row_id, [pt, of]))
return jobs, changed return jobs, changed
@ -162,6 +166,7 @@ def convert_bulk_epub(parent, db, comics, others):
parent.status_bar.showMessage(_('Starting Bulk conversion of %d books')%total, 2000) parent.status_bar.showMessage(_('Starting Bulk conversion of %d books')%total, 2000)
for i, row in enumerate(others+comics): for i, row in enumerate(others+comics):
row_id = db.id(row)
if row in others: if row in others:
data = None data = None
for fmt in EPUB_PREFERRED_SOURCE_FORMATS: for fmt in EPUB_PREFERRED_SOURCE_FORMATS:
@ -198,7 +203,7 @@ def convert_bulk_epub(parent, db, comics, others):
desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
temp_files = [cf] if cf is not None else [] temp_files = [cf] if cf is not None else []
temp_files.extend([opf_file, pt, of]) temp_files.extend([opf_file, pt, of])
jobs.append(('any2epub', args, desc, 'EPUB', db.id(row), temp_files)) jobs.append(('any2epub', args, desc, 'EPUB', row_id, temp_files))
else: else:
options = comic_opts.copy() options = comic_opts.copy()
mi = db.get_metadata(row) mi = db.get_metadata(row)
@ -224,7 +229,7 @@ def convert_bulk_epub(parent, db, comics, others):
options.verbose = 1 options.verbose = 1
args = [pt.name, options] args = [pt.name, options]
desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
jobs.append(('comic2epub', args, desc, 'EPUB', db.id(row), [pt, of])) jobs.append(('comic2epub', args, desc, 'EPUB', row_id, [pt, of]))
if bad_rows: if bad_rows:
res = [] res = []
@ -255,6 +260,7 @@ def convert_bulk_lrf(parent, db, comics, others):
parent.status_bar.showMessage(_('Starting Bulk conversion of %d books')%total, 2000) parent.status_bar.showMessage(_('Starting Bulk conversion of %d books')%total, 2000)
for i, row in enumerate(others+comics): for i, row in enumerate(others+comics):
row_id = db.id(row)
if row in others: if row in others:
cmdline = list(d.cmdline) cmdline = list(d.cmdline)
mi = db.get_metadata(row) mi = db.get_metadata(row)
@ -294,7 +300,7 @@ def convert_bulk_lrf(parent, db, comics, others):
desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
temp_files = [cf] if cf is not None else [] temp_files = [cf] if cf is not None else []
temp_files.extend([pt, of]) temp_files.extend([pt, of])
jobs.append(('any2lrf', [cmdline], desc, 'LRF', db.id(row), temp_files)) jobs.append(('any2lrf', [cmdline], desc, 'LRF', row_id, temp_files))
else: else:
options = comic_opts.copy() options = comic_opts.copy()
mi = db.get_metadata(row) mi = db.get_metadata(row)
@ -320,7 +326,7 @@ def convert_bulk_lrf(parent, db, comics, others):
options.verbose = 1 options.verbose = 1
args = [pt.name, options] args = [pt.name, options]
desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
jobs.append(('comic2lrf', args, desc, 'LRF', db.id(row), [pt, of])) jobs.append(('comic2lrf', args, desc, 'LRF', row_id, [pt, of]))
if bad_rows: if bad_rows:
res = [] res = []

View File

@ -83,9 +83,11 @@ STANZA_TEMPLATE='''\
<link py:if="record['cover']" rel="x-stanza-cover-image-thumbnail" type="image/png" href="${quote(record['cover'].replace(sep, '/')).replace('http%3A', 'http:')}" /> <link py:if="record['cover']" rel="x-stanza-cover-image-thumbnail" type="image/png" href="${quote(record['cover'].replace(sep, '/')).replace('http%3A', 'http:')}" />
<content type="xhtml"> <content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml"> <div xmlns="http://www.w3.org/1999/xhtml">
<py:for each="f in ('authors','publisher','rating','tags','series', 'isbn')"> <py:for each="f in ('authors', 'publisher', 'rating', 'tags', 'series', 'isbn')">
<py:if test="record[f]"> <py:if test="record[f]">
${f.capitalize()}:${unicode(', '.join(record[f]) if f=='tags' else record[f])}<br/> ${f.capitalize()}:${unicode(', '.join(record[f]) if f=='tags' else record[f])}
<py:if test="f =='series'"># ${str(record['series_index'])}</py:if>
<br/>
</py:if> </py:if>
</py:for> </py:for>
<py:if test="record['comments']"> <py:if test="record['comments']">
@ -231,7 +233,7 @@ NULL = DevNull()
def do_add(db, paths, one_book_per_directory, recurse, add_duplicates): def do_add(db, paths, one_book_per_directory, recurse, add_duplicates):
orig = sys.stdout orig = sys.stdout
sys.stdout = NULL #sys.stdout = NULL
try: try:
files, dirs = [], [] files, dirs = [], []
for path in paths: for path in paths:

View File

@ -17,7 +17,9 @@ from calibre.constants import terminal_controller, iswindows, isosx, \
from calibre.utils.lock import LockError, ExclusiveFile from calibre.utils.lock import LockError, ExclusiveFile
from collections import defaultdict from collections import defaultdict
if iswindows: if os.environ.has_key('CALIBRE_CONFIG_DIRECTORY'):
config_dir = os.path.abspath(os.environ['CALIBRE_CONFIG_DIRECTORY'])
elif iswindows:
config_dir = plugins['winutil'][0].special_folder_path(plugins['winutil'][0].CSIDL_APPDATA) config_dir = plugins['winutil'][0].special_folder_path(plugins['winutil'][0].CSIDL_APPDATA)
if not os.access(config_dir, os.W_OK|os.X_OK): if not os.access(config_dir, os.W_OK|os.X_OK):
config_dir = os.path.expanduser('~') config_dir = os.path.expanduser('~')

View File

@ -22,7 +22,7 @@ match to a given font specification. The main functions in this module are:
.. autofunction:: match .. autofunction:: match
''' '''
import sys, os, locale, codecs import sys, os, locale, codecs, subprocess, re
from ctypes import cdll, c_void_p, Structure, c_int, POINTER, c_ubyte, c_char, util, \ from ctypes import cdll, c_void_p, Structure, c_int, POINTER, c_ubyte, c_char, util, \
pointer, byref, create_string_buffer, Union, c_char_p, c_double pointer, byref, create_string_buffer, Union, c_char_p, c_double
@ -34,6 +34,7 @@ except:
iswindows = 'win32' in sys.platform or 'win64' in sys.platform iswindows = 'win32' in sys.platform or 'win64' in sys.platform
isosx = 'darwin' in sys.platform isosx = 'darwin' in sys.platform
isbsd = 'bsd' in sys.platform
DISABLED = False DISABLED = False
#if isosx: #if isosx:
# libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c')) # libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
@ -57,6 +58,13 @@ def load_library():
return cdll.LoadLibrary(lib) return cdll.LoadLibrary(lib)
elif iswindows: elif iswindows:
return cdll.LoadLibrary('libfontconfig-1') return cdll.LoadLibrary('libfontconfig-1')
elif isbsd:
raw = subprocess.Popen('pkg-config --libs-only-L fontconfig'.split(),
stdout=subprocess.PIPE).stdout.read().strip()
match = re.search(r'-L([^\s,]+)', raw)
if not match:
return cdll.LoadLibrary('libfontconfig.so')
return cdll.LoadLibrary(match.group(1)+'/libfontconfig.so')
else: else:
try: try:
return cdll.LoadLibrary(util.find_library('fontconfig')) return cdll.LoadLibrary(util.find_library('fontconfig'))

View File

@ -20,7 +20,7 @@ recipe_modules = ['recipe_' + r for r in (
'science_news', 'the_nation', 'lrb', 'harpers_full', 'liberation', 'science_news', 'the_nation', 'lrb', 'harpers_full', 'liberation',
'linux_magazine', 'telegraph_uk', 'utne', 'sciencedaily', 'forbes', 'linux_magazine', 'telegraph_uk', 'utne', 'sciencedaily', 'forbes',
'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik', 'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik',
'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet',
)] )]
import re, imp, inspect, time, os import re, imp, inspect, time, os

View File

@ -0,0 +1,49 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
Fetch FTD.
'''
from calibre.web.feeds.news import BasicNewsRecipe
class FTheiseDe(BasicNewsRecipe):
title = 'FTD'
description = 'Financial Times Deutschland'
__author__ = 'Oliver Niesner'
use_embedded_content = False
timefmt = ' [%d %b %Y]'
max_articles_per_feed = 40
no_stylesheets = True
remove_tags = [dict(id='navi_top'),
dict(id='topbanner'),
dict(id='seitenkopf'),
dict(id='footer'),
dict(id='rating_open'),
dict(id='ADS_Top'),
dict(id='ADS_Middle1'),
#dict(id='IDMS_ajax_chart_price_information_table'),
dict(id='ivwimg'),
dict(name='span', attrs={'class':'rsaquo'}),
dict(name='p', attrs={'class':'zwischenhead'}),
dict(name='div', attrs={'class':'chartBox'}),
dict(name='span', attrs={'class':'vote_455857'}),
dict(name='div', attrs={'class':'relatedhalb'}),
dict(name='div', attrs={'class':'bpoll'}),
dict(name='div', attrs={'class':'pollokknopf'}),
dict(name='div', attrs={'class':'videohint'}),
dict(name='div', attrs={'class':'videoshadow'}),
dict(name='div', attrs={'class':'boxresp videorahmen'}),
dict(name='div', attrs={'class':'boxresp'}),
dict(name='div', attrs={'class':'abspielen'}),
dict(name='div', attrs={'class':'wertungoben'}),
dict(name='div', attrs={'class':'artikelfuss'}),
dict(name='div', attrs={'class':'artikelsplitfaq'})]
remove_tags_after = [dict(name='div', attrs={'class':'artikelfuss'})]
feeds = [ ('FTD', 'http://www.ftd.de/static/ticker/ftd-topnews.rdf') ]

View File

@ -0,0 +1,46 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
Fetch zdnet.
'''
from calibre.web.feeds.news import BasicNewsRecipe
import re
class cdnet(BasicNewsRecipe):
title = 'zdnet'
description = 'zdnet security'
__author__ = 'Oliver Niesner'
use_embedded_content = False
timefmt = ' [%d %b %Y]'
max_articles_per_feed = 40
no_stylesheets = True
encoding = 'iso-8859-1'
#preprocess_regexps = \
# [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
# [
# (r'<84>', lambda match: ''),
# (r'<93>', lambda match: ''),
# ]
# ]
remove_tags = [dict(id='eyebrows'),
dict(id='header'),
dict(id='search'),
dict(id='nav'),
dict(id=''),
dict(name='div', attrs={'class':'banner'}),
dict(name='p', attrs={'class':'tags'}),
dict(name='div', attrs={'class':'special1'})]
remove_tags_after = [dict(name='div', attrs={'class':'bloggerDesc clear'})]
feeds = [ ('zdnet', 'http://feeds.feedburner.com/zdnet/security') ]