Sync to trunk

This commit is contained in:
John Schember 2009-01-22 16:48:21 -05:00
commit 37317ee345
16 changed files with 231 additions and 70 deletions

View File

@ -8,16 +8,18 @@ __docformat__ = 'restructuredtext en'
import sys, time, subprocess, os, re
from calibre import __appname__, __version__
INSTALLJAMMER = '/home/kovid/installjammer/installjammer'
sv = re.sub(r'[a-z]\d+', '', __version__)
cmdline = [
'/usr/local/installjammer/installjammer',
INSTALLJAMMER,
'--build-dir', '/tmp/calibre-installjammer',
'-DAppName', __appname__,
'-DShortAppName', __appname__,
'-DApplicationURL', 'http://%s.kovidgoyal.net'%__appname__,
'-DCopyright', time.strftime('%Y Kovid Goyal'),
'-DPackageDescription', '%s is an e-book library manager. It can view, convert and catalog e-books in most of the major e-book formats. It can also talk to a few e-book reader devices. It can go out to the internet and fetch metadata for your books. It can download newspapers and convert them into e-books for convenient reading.'%__appname__,
'-DPackageDescription', '%s is an e-book library manager. It can view, convert and catalog e-books in most of the major e-book formats. It can also talk to e-book reader devices. It can go out to the internet and fetch metadata for your books. It can download newspapers and convert them into e-books for convenient reading.'%__appname__,
'-DPackageSummary', '%s: E-book library management'%__appname__,
'-DVersion', __version__,
'-DInstallVersion', sv + '.0',

View File

@ -138,7 +138,7 @@ ProjectID
DA98A0C6-9102-73EC-2516-B147E972D3F7
ProjectVersion
1.2.7.0
1.2.12.0
SaveOnlyToplevelDirs
No
@ -211,7 +211,8 @@ File ::8E5D85A4-7608-47A1-CF7C-309060D5FF40 -filemethod {Always overwrite files}
Component ::F6829AB7-9F66-4CEE-CA0E-21F54C6D3609 -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows} -name Main -parent Components
SetupType ::D9ADE41C-B744-690C-2CED-CF826BF03D2E -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows} -name Typical -parent SetupTypes
InstallComponent 3EA07B17-04D8-6508-B535-96CC7173B49A -setup Install -type pane -title {Welcome Screen} -component Welcome -active Yes -parent StandardInstall
InstallComponent 3EA07B17-04D8-6508-B535-96CC7173B49A -setup Install -type pane -conditions D7F585DB-0DEC-A94E-DAB0-94D558D82764 -title {Welcome Screen} -component Welcome -command reorder -active Yes -parent StandardInstall
Condition D7F585DB-0DEC-A94E-DAB0-94D558D82764 -active Yes -parent 3EA07B17-04D8-6508-B535-96CC7173B49A -title {Execute Script Condition} -component ExecuteScriptCondition -TreeObject::id D7F585DB-0DEC-A94E-DAB0-94D558D82764
InstallComponent 7CCDA4BB-861C-C21E-3011-E93DB58F07D6 -setup Install -type action -title {Check for Previous Install} -component CheckForPreviousInstall -active Yes -parent 3EA07B17-04D8-6508-B535-96CC7173B49A
InstallComponent 580ACF2C-517F-5E48-9DEF-7DAEFBA59FDD -setup Install -type action -conditions 6DE3B369-9D6B-6BC1-4EA0-2C54ECE159EB -title {Set Virtual Text} -component SetVirtualText -command insert -active Yes -parent 3EA07B17-04D8-6508-B535-96CC7173B49A
Condition 6DE3B369-9D6B-6BC1-4EA0-2C54ECE159EB -active Yes -parent 580ACF2C-517F-5E48-9DEF-7DAEFBA59FDD -title {String Is Condition} -component StringIsCondition -TreeObject::id 6DE3B369-9D6B-6BC1-4EA0-2C54ECE159EB
@ -513,7 +514,7 @@ false
1
3EA07B17-04D8-6508-B535-96CC7173B49A,Conditions
{0 conditions}
{1 condition}
3EA07B17-04D8-6508-B535-96CC7173B49A,Message,subst
1
@ -1100,6 +1101,9 @@ AAFE58A0-2DFB-CA20-1F6E-D3815F885996,Alias
AIX-ppc,Active
No
AIX-ppc,BuildSeparateArchives
No
AIX-ppc,DefaultDirectoryPermission
0755
@ -1286,6 +1290,26 @@ CFBE4459-450B-1FAB-3422-609544334AA2,String
D79DC0D2-38BC-9D9F-2DF4-3C76D89BF933,ExitType
Finish
D7F585DB-0DEC-A94E-DAB0-94D558D82764,CheckCondition
{Before Next Pane is Displayed}
D7F585DB-0DEC-A94E-DAB0-94D558D82764,Comment
{Check if calibre.exe is still running}
D7F585DB-0DEC-A94E-DAB0-94D558D82764,FailureMessage
{calibre is still running. Please shut it down before proceeding. You can quit calibre by right clicking on the calibre system tray icon.}
D7F585DB-0DEC-A94E-DAB0-94D558D82764,ResultVirtualText
CalibreRunning
D7F585DB-0DEC-A94E-DAB0-94D558D82764,Script
{set pid [::InstallAPI::FindProcesses -name calibre.exe]
if {$pid eq ""} {
## myapp.exe is not running
return 1
}
return 0}
D86BBA5C-4903-33BA-59F8-4266A3D45896,Conditions
{2 conditions}
@ -1475,6 +1499,9 @@ FBA33088-C809-DD6B-D337-EADBF1CEE966,String
FreeBSD-4-x86,Active
No
FreeBSD-4-x86,BuildSeparateArchives
No
FreeBSD-4-x86,DefaultDirectoryPermission
0755
@ -1526,6 +1553,9 @@ FreeBSD-4-x86,RootInstallDir
FreeBSD-x86,Active
No
FreeBSD-x86,BuildSeparateArchives
No
FreeBSD-x86,DefaultDirectoryPermission
0755
@ -1577,6 +1607,9 @@ FreeBSD-x86,RootInstallDir
HPUX-hppa,Active
No
HPUX-hppa,BuildSeparateArchives
No
HPUX-hppa,DefaultDirectoryPermission
0755
@ -1628,6 +1661,9 @@ HPUX-hppa,RootInstallDir
Linux-x86,Active
No
Linux-x86,BuildSeparateArchives
No
Linux-x86,DefaultDirectoryPermission
0755
@ -1679,6 +1715,9 @@ Linux-x86,RootInstallDir
Solaris-sparc,Active
No
Solaris-sparc,BuildSeparateArchives
No
Solaris-sparc,DefaultDirectoryPermission
0755
@ -1730,6 +1769,9 @@ Solaris-sparc,RootInstallDir
TarArchive,Active
No
TarArchive,BuildSeparateArchives
No
TarArchive,CompressionLevel
6
@ -1790,9 +1832,15 @@ TarArchive,VirtualTextMap
Windows,Active
Yes
Windows,BuildSeparateArchives
No
Windows,Executable
<%AppName%>-<%Version%><%Ext%>
Windows,FileDescription
{<%AppName%> <%Version%> Setup}
Windows,IncludeTWAPI
Yes
@ -1829,6 +1877,9 @@ Windows,WindowsIcon
ZipArchive,Active
No
ZipArchive,BuildSeparateArchives
No
ZipArchive,CompressionLevel
6

View File

@ -16,7 +16,7 @@ from calibre.ebooks.epub import config as common_config, process_encryption
from calibre.ebooks.epub.from_html import convert as html2epub, find_html_index
from calibre.ptempfile import TemporaryDirectory
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.metadata.opf2 import OPFCreator
from calibre.ebooks.metadata.opf2 import OPFCreator, OPF
from calibre.utils.zipfile import ZipFile
from calibre.customize.ui import run_plugins_on_preprocess
@ -25,9 +25,36 @@ def lit2opf(path, tdir, opts):
print 'Exploding LIT file:', path
reader = LitReader(path)
reader.extract_content(tdir, False)
for f in walk(tdir):
if f.lower().endswith('.opf'):
return f
opf = None
for opf in walk(tdir):
if opf.lower().endswith('.opf'):
break
if not opf.endswith('.opf'):
opf = None
if opf is not None: # Check for url-quoted filenames
_opf = OPF(opf, os.path.dirname(opf))
replacements = []
for item in _opf.itermanifest():
href = item.get('href', '')
path = os.path.join(os.path.dirname(opf), *(href.split('/')))
if not os.path.exists(path) and os.path.exists(path.replace('&', '%26')):
npath = path
path = path.replace('&', '%26')
replacements.append((path, npath))
if replacements:
print 'Fixing quoted filenames...'
for path, npath in replacements:
if os.path.exists(path):
os.rename(path, npath)
for f in walk(tdir):
with open(f, 'r+b') as f:
raw = f.read()
for path, npath in replacements:
raw = raw.replace(os.path.basename(path), os.path.basename(npath))
f.seek(0)
f.truncate()
f.write(raw)
return opf
def mobi2opf(path, tdir, opts):
from calibre.ebooks.mobi.reader import MobiReader

View File

@ -6,33 +6,28 @@ Support for reading the metadata from a LIT file.
import sys, cStringIO, os
from calibre import relpath
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.metadata.opf import OPFReader
from calibre.ebooks.metadata.opf2 import OPF
from calibre.ebooks.lit.reader import LitReader
def get_metadata(stream):
try:
litfile = LitReader(stream)
src = litfile.meta.encode('utf-8')
mi = OPFReader(cStringIO.StringIO(src), dir=os.getcwd())
cover_url, cover_item = mi.cover, None
if cover_url:
cover_url = relpath(cover_url, os.getcwd())
for item in litfile.manifest.values():
if item.path == cover_url:
cover_item = item.internal
if cover_item is not None:
ext = cover_url.rpartition('.')[-1]
if not ext:
ext = 'jpg'
else:
ext = ext.lower()
cd = litfile.get_file('/data/' + cover_item)
mi.cover_data = (ext, cd) if cd else (None, None)
except:
title = stream.name if hasattr(stream, 'name') and stream.name else 'Unknown'
mi = MetaInformation(title, ['Unknown'])
litfile = LitReader(stream)
src = litfile.meta.encode('utf-8')
opf = OPF(cStringIO.StringIO(src), os.getcwd())
mi = MetaInformation(opf)
covers = []
for item in opf.iterguide():
if 'cover' not in item.get('type', '').lower():
continue
href = item.get('href', '')
candidates = [href, href.replace('&', '%26')]
for item in litfile.manifest.values():
if item.path in candidates:
covers.append(item.internal)
break
covers = [litfile.get_file('/data/' + i) for i in covers]
covers.sort(cmp=lambda x, y:cmp(len(x), len(y)))
mi.cover_data = ('jpg', covers[-1])
return mi
def main(args=sys.argv):

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
'''
'''
import sys, os
from calibre.ebooks.mobi.reader import get_metadata
def main(args=sys.argv):
if len(args) != 2:
print >>sys.stderr, 'Usage: %s file.mobi' % args[0]
return 1
fname = args[1]
mi = get_metadata(open(fname, 'rb'))
print unicode(mi)
if mi.cover_data[1]:
cover = os.path.abspath(
'.'.join((os.path.splitext(os.path.basename(fname))[0],
mi.cover_data[0].lower())))
open(cover, 'wb').write(mi.cover_data[1])
print _('Cover saved to'), cover
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -435,7 +435,7 @@ class OPF(object):
rating = MetadataField('rating', is_dc=False, formatter=int)
def __init__(self, stream, basedir=os.getcwdu()):
def __init__(self, stream, basedir=os.getcwdu(), unquote_urls=True):
if not hasattr(stream, 'read'):
stream = open(stream, 'rb')
self.basedir = self.base_dir = basedir
@ -446,7 +446,8 @@ class OPF(object):
if not self.metadata:
raise ValueError('Malformed OPF file: No <metadata> element')
self.metadata = self.metadata[0]
self.unquote_urls()
if unquote_urls:
self.unquote_urls()
self.manifest = Manifest()
m = self.manifest_path(self.root)
if m:

View File

@ -311,7 +311,7 @@ class MobiReader(object):
opf.cover = 'images/%05d.jpg'%(self.book_header.exth.cover_offset+1)
manifest = [(htmlfile, 'text/x-oeb1-document')]
bp = os.path.dirname(htmlfile)
for i in self.image_names:
for i in getattr(self, 'image_names', []):
manifest.append((os.path.join(bp, 'images/', i), 'image/jpg'))
opf.create_manifest(manifest)
@ -451,7 +451,7 @@ class MobiReader(object):
image_index += 1
try:
im = PILImage.open(buf)
except IOError, e:
except IOError:
continue
path = os.path.join(output_dir, '%05d.jpg'%image_index)
@ -476,31 +476,23 @@ def get_metadata(stream):
if mr.book_header.exth is None:
mi = MetaInformation(mr.name, [_('Unknown')])
else:
tdir = tempfile.mkdtemp('_mobi_meta', __appname__+'_')
atexit.register(shutil.rmtree, tdir)
#print tdir
mr.extract_images([], tdir)
mi = mr.create_opf('dummy.html')
if mi.cover:
cover = os.path.join(tdir, mi.cover)
if not os.access(cover, os.R_OK):
fname = os.path.basename(cover)
match = re.match(r'(\d+)(.+)', fname)
if match:
num, ext = int(match.group(1), 10), match.group(2)
while num > 0:
num -= 1
candidate = os.path.join(os.path.dirname(cover), '%05d%s'%(num, ext))
if os.access(candidate, os.R_OK):
cover = candidate
break
if os.access(cover, os.R_OK):
mi.cover_data = ('JPEG', open(os.path.join(tdir, cover), 'rb').read())
else:
path = os.path.join(tdir, 'images', '00001.jpg')
if os.access(path, os.R_OK):
mi.cover_data = ('JPEG', open(path, 'rb').read())
return mi
try:
if hasattr(mr.book_header.exth, 'cover_offset'):
cover_index = mr.book_header.first_image_index + mr.book_header.exth.cover_offset
data = mr.sections[cover_index][0]
else:
data = mr.sections[mr.book_header.first_image_index][0]
buf = cStringIO.StringIO(data)
im = PILImage.open(buf)
obuf = cStringIO.StringIO()
im.convert('RGBA').save(obuf, format='JPEG')
mi.cover_data = ('jpg', obuf.getvalue())
except:
import traceback
traceback.print_exc()
return mi
def option_parser():
from calibre.utils.config import OptionParser

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

View File

@ -162,7 +162,8 @@ class BooksModel(QAbstractTableModel):
def refresh_ids(self, ids, current_row=-1):
rows = self.db.refresh_ids(ids)
self.refresh_rows(rows, current_row=current_row)
if rows:
self.refresh_rows(rows, current_row=current_row)
def refresh_rows(self, rows, current_row=-1):
for row in rows:
@ -262,6 +263,16 @@ class BooksModel(QAbstractTableModel):
self.sorted_on = (self.column_map[col], order)
def refresh(self, reset=True):
try:
col = self.column_map.index(self.sorted_on[0])
except:
col = 0
self.db.refresh(field=self.column_map[col],
ascending=self.sorted_on[1]==Qt.AscendingOrder)
if reset:
self.reset()
def resort(self, reset=True):
try:
col = self.column_map.index(self.sorted_on[0])

View File

@ -478,7 +478,7 @@ class Main(MainWindow, Ui_MainWindow):
self.raise_()
self.activateWindow()
elif msg.startswith('refreshdb:'):
self.library_view.model().resort()
self.library_view.model().refresh()
self.library_view.model().research()
else:
print msg

View File

@ -29,5 +29,5 @@ def server_config(defaults=None):
c.add_opt('develop', ['--develop'], default=False,
help='Development mode. Server automatically restarts on file changes and serves code files (html, css, js) from the file system instead of calibre\'s resource system.')
c.add_opt('max_cover', ['--max-cover'], default='600x800',
help=_('The maximum size for displayed covers'))
help=_('The maximum size for displayed covers. Default is %default.'))
return c

View File

@ -40,7 +40,7 @@ function create_table_headers() {
function format_url(format, id, title) {
return 'get/'+format.toLowerCase() + '/'+title + '_' + id+'.'+format.toLowerCase();
return 'get/'+format.toLowerCase() + '/'+encodeURIComponent(title) + '_' + id+'.'+format.toLowerCase();
}
function render_book(book) {

View File

@ -26,6 +26,7 @@ entry_points = {
'opf-meta = calibre.ebooks.metadata.opf2:main',
'odt-meta = calibre.ebooks.metadata.odt:main',
'epub-meta = calibre.ebooks.metadata.epub:main',
'mobi-meta = calibre.ebooks.metadata.mobi:main',
'txt2lrf = calibre.ebooks.lrf.txt.convert_from:main',
'html2lrf = calibre.ebooks.lrf.html.convert_from:main',
'html2oeb = calibre.ebooks.html:main',
@ -423,7 +424,7 @@ def install_man_pages(fatal_errors):
if prog in ('prs500', 'pdf-meta', 'epub-meta', 'lit-meta',
'markdown-calibre', 'calibre-debug', 'fb2-meta',
'calibre-fontconfig', 'calibre-parallel', 'odt-meta',
'rb-meta', 'imp-meta'):
'rb-meta', 'imp-meta', 'mobi-meta'):
continue
help2man = ('help2man', prog, '--name', 'part of %s'%__appname__,

View File

@ -5,9 +5,8 @@ Dynamic language lookup of translations for user-visible strings.
__license__ = 'GPL v3'
__copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
import sys
from cStringIO import StringIO
from gettext import GNUTranslations, NullTranslations
from gettext import GNUTranslations
from calibre.translations.compiled import translations
__all__ = ['translate']
@ -23,5 +22,5 @@ def translate(lang, text):
trans = GNUTranslations(buf)
_CACHE[lang] = trans
if trans is None:
return _(text)
return getattr(__builtins__, '_', lambda x: x)(text)
return trans.ugettext(text)

View File

@ -23,7 +23,7 @@ recipe_modules = ['recipe_' + r for r in (
'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet',
'joelonsoftware', 'telepolis', 'common_dreams', 'nin', 'tomshardware_de',
'pagina12', 'infobae', 'ambito', 'elargentino', 'sueddeutsche', 'the_age',
'laprensa',
'laprensa', 'amspec',
)]
import re, imp, inspect, time, os

View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
'''
spectator.org
'''
from calibre.web.feeds.news import BasicNewsRecipe
class TheAmericanSpectator(BasicNewsRecipe):
title = 'The American Spectator'
__author__ = 'Darko Miletic'
description = 'news from USA'
oldest_article = 7
max_articles_per_feed = 100
no_stylesheets = True
use_embedded_content = False
INDEX = 'http://spectator.org'
html2lrf_options = [
'--comment' , description
, '--category' , 'news, politics, USA'
, '--publisher' , title
]
keep_only_tags = [
dict(name='div', attrs={'class':'post inner'})
,dict(name='div', attrs={'class':'author-bio'})
]
remove_tags = [
dict(name='object')
,dict(name='div', attrs={'class':'col3' })
,dict(name='div', attrs={'class':'post-options' })
,dict(name='p' , attrs={'class':'letter-editor'})
,dict(name='div', attrs={'class':'social' })
]
feeds = [ (u'Articles', u'http://feedproxy.google.com/amspecarticles')]
def get_cover_url(self):
cover_url = None
soup = self.index_to_soup(self.INDEX)
link_item = soup.find('a',attrs={'class':'cover'})
if link_item:
soup2 = self.index_to_soup(link_item['href'])
link_item2 = soup2.find('div',attrs={'class':'post inner issues'})
cover_url = self.INDEX + link_item2.img['src']
return cover_url
def print_version(self, url):
return url + '/print'