Sync to trunk.

This commit is contained in:
John Schember 2009-08-09 14:49:53 -04:00
commit c5e5903eb8
16 changed files with 320 additions and 80 deletions

View File

@ -28,6 +28,7 @@ def freeze():
binary_includes = [ binary_includes = [
'/usr/bin/pdftohtml', '/usr/bin/pdftohtml',
'/usr/bin/calibre-mount-helper',
'/usr/lib/libunrar.so', '/usr/lib/libunrar.so',
'/usr/lib/libsqlite3.so.0', '/usr/lib/libsqlite3.so.0',
'/usr/lib/libsqlite3.so.0', '/usr/lib/libsqlite3.so.0',

View File

@ -45,6 +45,24 @@ main_functions = {
'gui' : [_ep_to_function(i) for i in entry_points['gui_scripts']], 'gui' : [_ep_to_function(i) for i in entry_points['gui_scripts']],
} }
def setup_mount_helper():
def warn():
print 'WARNING: Failed to compile mount helper. Auto mounting of',
print 'devices will not work'
if os.geteuid() != 0:
return warn()
import stat
src = os.path.join('src', 'calibre', 'devices', 'linux_mount_helper.c')
dest = '/usr/bin/calibre-mount-helper'
p = subprocess.Popen(['gcc', '-Wall', src, '-o', dest])
ret = p.wait()
if ret != 0:
return warn()
os.chown(dest, 0, 0)
os.chmod(dest,
stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
if __name__ == '__main__': if __name__ == '__main__':
from setuptools import setup, find_packages from setuptools import setup, find_packages
from pyqtdistutils import PyQtExtension, build_ext, Extension from pyqtdistutils import PyQtExtension, build_ext, Extension
@ -68,7 +86,11 @@ if __name__ == '__main__':
qt_inc = qt_inc if qt_inc not in ('', '**Unknown**') and os.path.isdir(qt_inc) else None qt_inc = qt_inc if qt_inc not in ('', '**Unknown**') and os.path.isdir(qt_inc) else None
qt_lib = qmake_query('QT_INSTALL_LIBS').splitlines()[0] qt_lib = qmake_query('QT_INSTALL_LIBS').splitlines()[0]
qt_lib = qt_lib if qt_lib not in ('', '**Unknown**') and os.path.isdir(qt_lib) else None qt_lib = qt_lib if qt_lib not in ('', '**Unknown**') and os.path.isdir(qt_lib) else None
if qt_lib is None or qt_inc is None:
print 'WARNING: Could not find QT librariers and headers.',
print 'Is qmake in your PATH?'
if iswindows: if iswindows:
optional.append(Extension('calibre.plugins.winutil', optional.append(Extension('calibre.plugins.winutil',
sources=['src/calibre/utils/windows/winutil.c'], sources=['src/calibre/utils/windows/winutil.c'],
@ -90,7 +112,8 @@ if __name__ == '__main__':
poppler_inc = '/Volumes/sw/build/poppler-0.10.7/qt4/src' poppler_inc = '/Volumes/sw/build/poppler-0.10.7/qt4/src'
poppler_lib = '/Users/kovid/poppler/lib' poppler_lib = '/Users/kovid/poppler/lib'
poppler_inc = os.environ.get('POPPLER_INC_DIR', poppler_inc) poppler_inc = os.environ.get('POPPLER_INC_DIR', poppler_inc)
if os.path.exists(os.path.join(poppler_inc, 'poppler-qt4.h')): if os.path.exists(os.path.join(poppler_inc, 'poppler-qt4.h'))\
and qt_lib is not None and qt_inc is not None:
optional.append(Extension('calibre.plugins.calibre_poppler', optional.append(Extension('calibre.plugins.calibre_poppler',
sources=['src/calibre/utils/poppler/poppler.cpp'], sources=['src/calibre/utils/poppler/poppler.cpp'],
libraries=(['poppler', 'poppler-qt4']+poppler_libs), libraries=(['poppler', 'poppler-qt4']+poppler_libs),
@ -253,6 +276,7 @@ if __name__ == '__main__':
if 'develop' in ' '.join(sys.argv) and islinux: if 'develop' in ' '.join(sys.argv) and islinux:
subprocess.check_call('calibre_postinstall --do-not-reload-udev-hal', shell=True) subprocess.check_call('calibre_postinstall --do-not-reload-udev-hal', shell=True)
setup_mount_helper()
if 'install' in sys.argv and islinux: if 'install' in sys.argv and islinux:
subprocess.check_call('calibre_postinstall', shell=True) subprocess.check_call('calibre_postinstall', shell=True)
setup_mount_helper()

View File

@ -0,0 +1,141 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MARKER ".created_by_calibre_mount_helper"
int exists(char *path) {
struct stat file_info;
if (stat(path, &file_info) == 0) return 1;
return 0;
}
int get_root() {
int res;
res = setreuid(0, 0);
if (res != 0) return 1;
if (setregid(0, 0) != 0) return 1;
return 0;
}
int do_mount(char *dev, char *mp) {
char options[1000];
char marker[2000];
if (exists(dev) == 0) {
fprintf(stderr, "Specified device node does not exist\n");
return EXIT_FAILURE;
}
if (exists(mp) == 0) {
if (mkdir(mp, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) {
int errsv = errno;
fprintf(stderr, "Failed to create mount point with error: %s\n", strerror(errsv));
}
}
strncat(marker, mp, strlen(mp));
strncat(marker, "/", 1);
strncat(marker, MARKER, strlen(MARKER));
if (exists(marker) == 0) {
int fd = creat(marker, S_IRUSR|S_IWUSR);
if (fd == -1) {
int errsv = errno;
fprintf(stderr, "Failed to create marker with error: %s\n", strerror(errsv));
return EXIT_FAILURE;
}
close(fd);
}
snprintf(options, 1000, "rw,noexec,nosuid,sync,nodev,quiet,shortname=mixed,uid=%d,gid=%d,umask=077,fmask=0177,dmask=0077,utf8,iocharset=iso8859-1", getuid(), getgid());
if (get_root() != 0) {
fprintf(stderr, "Failed to elevate to root privileges\n");
return EXIT_FAILURE;
}
execlp("mount", "mount", "-t", "vfat", "-o", options, dev, mp, NULL);
int errsv = errno;
fprintf(stderr, "Failed to mount with error: %s\n", strerror(errsv));
return EXIT_FAILURE;
}
int do_eject(char *dev, char*mp) {
char marker[2000];
int status = EXIT_FAILURE, ret;
if (get_root() != 0) {
fprintf(stderr, "Failed to elevate to root privileges\n");
return EXIT_FAILURE;
}
int pid = fork();
if (pid == -1) {
fprintf(stderr, "Failed to fork\n");
return EXIT_FAILURE;
}
if (pid == 0) {
if (get_root() != 0) {
fprintf(stderr, "Failed to elevate to root privileges\n");
return EXIT_FAILURE;
}
execlp("eject", "eject", "-s", dev, NULL);
int errsv = errno;
fprintf(stderr, "Failed to eject with error: %s\n", strerror(errsv));
return EXIT_FAILURE;
} else {
int i;
for (i =0; i < 7; i++) {
sleep(1);
ret = waitpid(pid, &status, WNOHANG);
if (ret == -1) return EXIT_FAILURE;
if (ret > 0) break;
}
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
strncat(marker, mp, strlen(mp));
strncat(marker, "/", 1);
strncat(marker, MARKER, strlen(MARKER));
if (exists(marker)) {
int urt = unlink(marker);
if (urt == -1) {
fprintf(stderr, "Failed to unlink marker: %s\n", strerror(errno));
return EXIT_FAILURE;
}
int rmd = rmdir(mp);
if (rmd == -1) {
fprintf(stderr, "Failed to remove mount point: %s\n", strerror(errno));
return EXIT_FAILURE;
}
}
}
}
return EXIT_SUCCESS;
}
int main(int argc, char** argv)
{
char *action, *dev, *mp;
/*printf("Real UID\t= %d\n", getuid());
printf("Effective UID\t= %d\n", geteuid());
printf("Real GID\t= %d\n", getgid());
printf("Effective GID\t= %d\n", getegid());*/
if (argc != 4) {
fprintf(stderr, "Needs 3 arguments: action, device node and mount point\n");
return EXIT_FAILURE;
}
action = argv[1]; dev = argv[2]; mp = argv[3];
if (strncmp(action, "mount", 5) == 0) {
return do_mount(dev, mp);
}
else if (strncmp(action, "eject", 7) == 0) {
return do_eject(dev, mp);
} else {
fprintf(stderr, "Unrecognized action: must be mount or eject\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

View File

@ -226,7 +226,6 @@ def main():
try: try:
dev.open()
if command == "df": if command == "df":
total = dev.total_space(end_session=False) total = dev.total_space(end_session=False)
free = dev.free_space() free = dev.free_space()

View File

@ -17,7 +17,6 @@ import time
import re import re
import sys import sys
import glob import glob
import shutil
from itertools import repeat from itertools import repeat
from math import ceil from math import ceil
@ -489,7 +488,7 @@ class Device(DeviceConfig, DevicePlugin):
label = self.STORAGE_CARD_VOLUME_LABEL label = self.STORAGE_CARD_VOLUME_LABEL
if type == 'cardb': if type == 'cardb':
label = self.STORAGE_CARD2_VOLUME_LABEL label = self.STORAGE_CARD2_VOLUME_LABEL
if label is None: if not label:
label = self.STORAGE_CARD_VOLUME_LABEL + ' 2' label = self.STORAGE_CARD_VOLUME_LABEL + ' 2'
extra = 0 extra = 0
while True: while True:
@ -501,11 +500,15 @@ class Device(DeviceConfig, DevicePlugin):
label += ' (%d)'%extra label += ' (%d)'%extra
def do_mount(node, label): def do_mount(node, label):
cmd = ['pmount', '-w', '-s'] cmd = 'calibre-mount-helper'
if getattr(sys, 'frozen_path', False):
cmd = os.path.join(sys.frozen_path, cmd)
cmd = [cmd, 'mount']
try: try:
p = subprocess.Popen(cmd + [node, label]) p = subprocess.Popen(cmd + [node, '/media/'+label])
except OSError: except OSError:
raise DeviceError(_('You must install the pmount package.')) raise DeviceError(
_('Could not find mount helper: %s.')%cmd[0])
while p.poll() is None: while p.poll() is None:
time.sleep(0.1) time.sleep(0.1)
return p.returncode return p.returncode
@ -520,11 +523,13 @@ class Device(DeviceConfig, DevicePlugin):
raise DeviceError(_('Unable to detect the %s disk drive.') raise DeviceError(_('Unable to detect the %s disk drive.')
%self.__class__.__name__) %self.__class__.__name__)
self._linux_mount_map = {}
mp, ret = mount(main, 'main') mp, ret = mount(main, 'main')
if mp is None: if mp is None:
raise DeviceError( raise DeviceError(
_('Unable to mount main memory (Error code: %d)')%ret) _('Unable to mount main memory (Error code: %d)')%ret)
if not mp.endswith('/'): mp += '/' if not mp.endswith('/'): mp += '/'
self._linux_mount_map[main] = mp
self._main_prefix = mp self._main_prefix = mp
cards = [(carda, '_card_a_prefix', 'carda'), cards = [(carda, '_card_a_prefix', 'carda'),
(cardb, '_card_b_prefix', 'cardb')] (cardb, '_card_b_prefix', 'cardb')]
@ -536,6 +541,7 @@ class Device(DeviceConfig, DevicePlugin):
else: else:
if not mp.endswith('/'): mp += '/' if not mp.endswith('/'): mp += '/'
setattr(self, prefix, mp) setattr(self, prefix, mp)
self._linux_mount_map[card] = mp
def open(self): def open(self):
time.sleep(5) time.sleep(5)
@ -595,27 +601,16 @@ class Device(DeviceConfig, DevicePlugin):
success = False success = False
for drive in drives: for drive in drives:
if drive: if drive:
cmd = ['pumount', '-l'] cmd = 'calibre-mount-helper'
if getattr(sys, 'frozen_path', False):
cmd = os.path.join(sys.frozen_path, cmd)
cmd = [cmd, 'eject']
mp = getattr(self, "_linux_mount_map", {}).get(drive,
'dummy/')[:-1]
try: try:
p = subprocess.Popen(cmd + [drive]) subprocess.Popen(cmd + [drive, mp]).wait()
except: except:
pass pass
while p.poll() is None:
time.sleep(0.1)
success = success or p.returncode == 0
try:
subprocess.Popen(['sudo', 'eject', drive])
except:
pass
for x in ('_main_prefix', '_card_a_prefix', '_card_b_prefix'):
x = getattr(self, x, None)
if x is not None:
if x.startswith('/media/') and os.path.exists(x) \
and not os.listdir(x):
try:
shutil.rmtree(x)
except:
pass
def eject(self): def eject(self):
if islinux: if islinux:

View File

@ -19,6 +19,8 @@ def get_metadata(stream):
author= [firstname+" "+lastname] author= [firstname+" "+lastname]
title = soup.find("book-title").string title = soup.find("book-title").string
comments = soup.find("annotation") comments = soup.find("annotation")
tags = soup.findAll('genre')
tags = [t.contents[0] for t in tags]
cp = soup.find('coverpage') cp = soup.find('coverpage')
cdata = None cdata = None
if cp: if cp:
@ -39,6 +41,8 @@ def get_metadata(stream):
mi = MetaInformation(title, author) mi = MetaInformation(title, author)
mi.comments = comments mi.comments = comments
mi.author_sort = lastname+'; '+firstname mi.author_sort = lastname+'; '+firstname
if tags:
mi.tags = tags
if series: if series:
mi.series = series.get('name', None) mi.series = series.get('name', None)
try: try:

View File

@ -78,7 +78,10 @@ class EXTHHeader(object):
if id == 100: if id == 100:
if self.mi.authors == [_('Unknown')]: if self.mi.authors == [_('Unknown')]:
self.mi.authors = [] self.mi.authors = []
self.mi.authors.append(content.decode(codec, 'ignore').strip()) au = content.decode(codec, 'ignore').strip()
self.mi.authors.append(au)
if re.match(r'\S+?\s*,\s+\S+', au.strip()):
self.mi.author_sort = au.strip()
elif id == 101: elif id == 101:
self.mi.publisher = content.decode(codec, 'ignore').strip() self.mi.publisher = content.decode(codec, 'ignore').strip()
elif id == 103: elif id == 103:

View File

@ -795,14 +795,18 @@ class Manifest(object):
def first_pass(data): def first_pass(data):
try: try:
data = etree.fromstring(data) data = etree.fromstring(data)
except etree.XMLSyntaxError: except etree.XMLSyntaxError, err:
repl = lambda m: ENTITYDEFS.get(m.group(1), m.group(0)) repl = lambda m: ENTITYDEFS.get(m.group(1), m.group(0))
data = ENTITY_RE.sub(repl, data) data = ENTITY_RE.sub(repl, data)
try: try:
data = etree.fromstring(data) data = etree.fromstring(data)
except etree.XMLSyntaxError: except etree.XMLSyntaxError, err:
self.oeb.logger.warn('Parsing file %r as HTML' % self.href) self.oeb.logger.warn('Parsing file %r as HTML' % self.href)
data = html.fromstring(data) if err.args and err.args[0].startswith('Excessive depth'):
from lxml.html import soupparser
data = soupparser.fromstring(data)
else:
data = html.fromstring(data)
data.attrib.pop('xmlns', None) data.attrib.pop('xmlns', None)
for elem in data.iter(tag=etree.Comment): for elem in data.iter(tag=etree.Comment):
if elem.text: if elem.text:

View File

@ -183,7 +183,12 @@ class CSSFlattener(object):
elif value <= slineh: elif value <= slineh:
cssdict[property] = "%0.5fem" % (dlineh / fsize) cssdict[property] = "%0.5fem" % (dlineh / fsize)
else: else:
value = round(value / slineh) * dlineh try:
value = round(value / slineh) * dlineh
except:
self.oeb.logger.warning(
'Invalid length:', value)
value = 0.0
cssdict[property] = "%0.5fem" % (value / fsize) cssdict[property] = "%0.5fem" % (value / fsize)
def flatten_node(self, node, stylizer, names, styles, psize, left=0): def flatten_node(self, node, stylizer, names, styles, psize, left=0):

View File

@ -6,32 +6,60 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import cStringIO
from calibre import fit_image from calibre import fit_image
class RescaleImages(object): class RescaleImages(object):
'Rescale all images to fit inside given screen size' 'Rescale all images to fit inside given screen size'
def __call__(self, oeb, opts): def __call__(self, oeb, opts):
from PyQt4.Qt import QApplication, QImage, Qt
from calibre.gui2 import pixmap_to_data
self.oeb, self.opts, self.log = oeb, opts, oeb.log self.oeb, self.opts, self.log = oeb, opts, oeb.log
page_width, page_height = opts.dest.width, opts.dest.height from calibre.gui2 import is_ok_to_use_qt
for item in oeb.manifest: self.rescale(qt=is_ok_to_use_qt())
def rescale(self, qt=True):
from PyQt4.Qt import QImage, Qt
from calibre.gui2 import pixmap_to_data
try:
from PIL import Image as PILImage
PILImage
except ImportError:
import Image as PILImage
page_width, page_height = self.opts.dest.width, self.opts.dest.height
for item in self.oeb.manifest:
if item.media_type.startswith('image'): if item.media_type.startswith('image'):
raw = item.data raw = item.data
if not raw: continue if not raw: continue
if QApplication.instance() is None: if qt:
QApplication([]) img = QImage(10, 10, QImage.Format_ARGB32_Premultiplied)
if not img.loadFromData(raw): continue
width, height = img.width(), img.height()
else:
f = cStringIO.StringIO(raw)
try:
im = PILImage.open(f)
except IOError:
continue
width, height = im.size
img = QImage(10, 10, QImage.Format_ARGB32_Premultiplied)
if not img.loadFromData(raw): continue
width, height = img.width(), img.height()
scaled, new_width, new_height = fit_image(width, height, scaled, new_width, new_height = fit_image(width, height,
page_width, page_height) page_width, page_height)
if scaled: if scaled:
self.log('Rescaling image', item.href) self.log('Rescaling image', item.href)
img = img.scaled(new_width, new_height, if qt:
Qt.IgnoreAspectRatio, Qt.SmoothTransformation) img = img.scaled(new_width, new_height,
item.data = pixmap_to_data(img) Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
item.data = pixmap_to_data(img)
else:
im = im.resize((int(new_width), int(new_height)), PILImage.ANTIALIAS)
of = cStringIO.StringIO()
im.convert('RGB').save(of, 'JPEG')
item.data = of.getvalue()

View File

@ -103,56 +103,50 @@ def available_width():
def extension(path): def extension(path):
return os.path.splitext(path)[1][1:].lower() return os.path.splitext(path)[1][1:].lower()
class MessageBox(QMessageBox):
def __init__(self, type_, title, msg, buttons, parent, det_msg=''):
QMessageBox.__init__(self, type_, title, msg, buttons, parent)
self.title = title
self.msg = msg
self.det_msg = det_msg
self.setDetailedText(det_msg)
self.cb = QPushButton(_('Copy to Clipboard'))
self.layout().addWidget(self.cb)
self.connect(self.cb, SIGNAL('clicked()'), self.copy_to_clipboard)
def copy_to_clipboard(self):
QApplication.clipboard().setText('%s: %s\n\n%s' %
(self.title, self.msg, self.det_msg))
def warning_dialog(parent, title, msg, det_msg='', show=False): def warning_dialog(parent, title, msg, det_msg='', show=False):
d = QMessageBox(QMessageBox.Warning, 'WARNING: '+title, msg, QMessageBox.Ok, d = MessageBox(QMessageBox.Warning, 'WARNING: '+title, msg, QMessageBox.Ok,
parent) parent, det_msg)
d.setDetailedText(det_msg)
d.setIconPixmap(QPixmap(':/images/dialog_warning.svg')) d.setIconPixmap(QPixmap(':/images/dialog_warning.svg'))
clipboard_button = QPushButton(_('Copy to Clipboard'))
d.layout().addWidget(clipboard_button)
def copy_to_clipboard():
QApplication.clipboard().setText('%s - %s: %s' % (title, msg, det_msg))
d.connect(clipboard_button, SIGNAL('clicked()'), copy_to_clipboard)
if show: if show:
return d.exec_() return d.exec_()
return d return d
def error_dialog(parent, title, msg, det_msg='', show=False): def error_dialog(parent, title, msg, det_msg='', show=False):
d = QMessageBox(QMessageBox.Critical, 'ERROR: '+title, msg, QMessageBox.Ok, d = MessageBox(QMessageBox.Critical, 'ERROR: '+title, msg, QMessageBox.Ok,
parent) parent, det_msg)
d.setDetailedText(det_msg)
d.setIconPixmap(QPixmap(':/images/dialog_error.svg')) d.setIconPixmap(QPixmap(':/images/dialog_error.svg'))
clipboard_button = QPushButton(_('Copy to Clipboard'))
d.layout().addWidget(clipboard_button)
def copy_to_clipboard():
QApplication.clipboard().setText('%s - %s: %s' % (title, msg, det_msg))
d.connect(clipboard_button, SIGNAL('clicked()'), copy_to_clipboard)
if show: if show:
return d.exec_() return d.exec_()
return d return d
def question_dialog(parent, title, msg, det_msg=''): def question_dialog(parent, title, msg, det_msg=''):
d = QMessageBox(QMessageBox.Question, title, msg, QMessageBox.Yes|QMessageBox.No, d = MessageBox(QMessageBox.Question, title, msg, QMessageBox.Yes|QMessageBox.No,
parent) parent, det_msg)
d.setDetailedText(det_msg)
d.setIconPixmap(QPixmap(':/images/dialog_information.svg')) d.setIconPixmap(QPixmap(':/images/dialog_information.svg'))
clipboard_button = QPushButton(_('Copy to Clipboard'))
d.layout().addWidget(clipboard_button)
def copy_to_clipboard():
QApplication.clipboard().setText('%s - %s: %s' % (title, msg, det_msg))
d.connect(clipboard_button, SIGNAL('clicked()'), copy_to_clipboard)
return d.exec_() == QMessageBox.Yes return d.exec_() == QMessageBox.Yes
def info_dialog(parent, title, msg, det_msg='', show=False): def info_dialog(parent, title, msg, det_msg='', show=False):
d = QMessageBox(QMessageBox.Information, title, msg, QMessageBox.NoButton, d = MessageBox(QMessageBox.Information, title, msg, QMessageBox.NoButton,
parent) parent, det_msg)
d.setDetailedText(det_msg)
d.setIconPixmap(QPixmap(':/images/dialog_information.svg')) d.setIconPixmap(QPixmap(':/images/dialog_information.svg'))
clipboard_button = QPushButton(_('Copy to Clipboard'))
d.layout().addWidget(clipboard_button)
def copy_to_clipboard():
QApplication.clipboard().setText('%s - %s: %s' % (title, msg, det_msg))
d.connect(clipboard_button, SIGNAL('clicked()'), copy_to_clipboard)
if show: if show:
return d.exec_() return d.exec_()
return d return d
@ -273,6 +267,7 @@ class FileIconProvider(QFileIconProvider):
'azw' : 'mobi', 'azw' : 'mobi',
'mobi' : 'mobi', 'mobi' : 'mobi',
'epub' : 'epub', 'epub' : 'epub',
'fb2' : 'fb2',
} }
def __init__(self): def __init__(self):

View File

@ -129,7 +129,12 @@ class Adder(QObject):
mi = MetaInformation('', [_('Unknown')]) mi = MetaInformation('', [_('Unknown')])
self.critical[name] = open(opf, 'rb').read().decode('utf-8', 'replace') self.critical[name] = open(opf, 'rb').read().decode('utf-8', 'replace')
else: else:
mi = MetaInformation(OPF(opf)) try:
mi = MetaInformation(OPF(opf))
except:
import traceback
mi = MetaInformation('', [_('Unknown')])
self.critical[name] = traceback.format_exc()
if not mi.title: if not mi.title:
mi.title = os.path.splitext(name)[0] mi.title = os.path.splitext(name)[0]
mi.title = mi.title if isinstance(mi.title, unicode) else \ mi.title = mi.title if isinstance(mi.title, unicode) else \

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="32px" height="32px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<image overflow="visible" width="32" height="32" xlink:href="data:image/gif;base64,R0lGODlhIAAgAOYAAP////X19eXl5ayws/n5+YCAgKCjpejo6PDw8KqtsJ6gov+UAKOmqJeZm6er
rfz8/P+ZAaWoq5SWl5qdnpyeoIWFhubm5oyNjoaHh5aYmoGBgZibnoSEhIODg4mJio6PkI+Rkv+c
CpKTlIKCgv/itf+sMP+6UouMjf/254eIiO3t7f/TkvHx8YqLi//FbsPDw//px/+0Rv/99f/x27u7
u/+jG////fLy8v//+sXFxeDg4IGCgtLS0vPz8+fn57i4ucvLy52foe7u7vf4+ImKi8rKyYeIifr6
+fX19svKy9DPz4WGh9TU1Ly8vKaqrNzc3NXW1YaGh46QkZ+io/T09NrZ2gAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5
BAAAAAAALAAAAAAgACAAAAf/gAOCg4QJhg6IEREMDAaOCgAPkgSUBISXhgmJi4yPChSSD5UEAZeY
h5udj5GTlaaDmamqCp+ho6WmsbKOBrQUE62UAbiFqIqcnp8TG6LCw8Q8Si8OL1VFiqq9n78bDZXP
w4I+AEdIDgEAPsiev8sN3qTguDcAAEznAAKz2+4NGc7gEBjqAYCAIXQCePma0C8DgBkk5CEQSINK
JB4JEACw8OKADgPc3mVwiKLEghXPJiLAV6+Uxgf1AKhoKAFAyQUQTgZQuRLKkEg0BqAD8AQmgm7+
at4MUSPESZUqIjgRAiCAI3QHJhAAgCCpUpMuUACAYXIFAhVRGbCo2guhVq4Z/yR8xbnCRQwAJHKu
QMuIXoBPCL1xlWvTJAQITkvgzXlShYEpfn8F3oqgJgAXOA9DcCEDRg2cC0LMMBCEYIBlCP9xFQEC
AA4TmV3YWFEjRs4QJA7QWhugG0IJlEGA+ABABmzRNmCggIE49wEKFHj7QyiC8ocLF064jrEghonv
JXAfGM+Qd1zqlLGfaOEBgA3Yh0M7H79hA2+5CEFQXu/BQwoMrsEn3ngHWPDOfSIg9AFl7P2HQQUc
FGcCBPMVKIA/vImQoEzVceXfgxB2MEJxMxBooQBx8SbcUBpV9V8FIY6ggQYmWmCBADjiV9BwW21V
jw4PctCBiBoUYOR4NuKIo2OGP7xAA3ZNvJBDDkAkAaOQMhZpZAEF3qikAKxJcV12RBiBQRRLhEik
llsm+aUAw13H34dXirgDm1sW4OWbY/LnIIRYzphnnm8qGWd27NEZ452DGrnnl302iEGQgeJJaKEC
BAIAOw==">
</image>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -153,7 +153,7 @@ def do_list(db, fields, sort_by, ascending, search_text, line_width, separator,
break break
widths = list(base_widths) widths = list(base_widths)
titles = map(lambda x, y: '%-*s'%(x, y), widths, fields) titles = map(lambda x, y: '%-*s%s'%(x-len(separator), y, separator), widths, fields)
print terminal_controller.GREEN + ''.join(titles)+terminal_controller.NORMAL print terminal_controller.GREEN + ''.join(titles)+terminal_controller.NORMAL
wrappers = map(lambda x: TextWrapper(x-1), widths) wrappers = map(lambda x: TextWrapper(x-1), widths)

View File

@ -1,6 +1,8 @@
{% extends "!layout.html" %} {% extends "!layout.html" %}
{% block sidebarlogo %} {% block sidebarlogo %}
{{ super() }} <p class="logo">
<a href="http://calibre.kovidgoyal.net"><img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/></a>
</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="3028915" /> <input type="hidden" name="hosted_button_id" value="3028915" />

View File

@ -21,7 +21,6 @@ DEPENDENCIES = [
('dnspython', '1.6.0', 'dnspython', 'dnspython', 'dnspython', 'dnspython'), ('dnspython', '1.6.0', 'dnspython', 'dnspython', 'dnspython', 'dnspython'),
('poppler-qt4', '0.10.6', 'poppler-qt4', 'poppler-qt4', 'poppler-qt4', 'poppler-qt4'), ('poppler-qt4', '0.10.6', 'poppler-qt4', 'poppler-qt4', 'poppler-qt4', 'poppler-qt4'),
('podofo', '0.7', 'podofo', 'podofo', 'podofo', 'podofo'), ('podofo', '0.7', 'podofo', 'podofo', 'podofo', 'podofo'),
('pmount', '0.9.19', 'pmount', 'pmount', 'pmount', 'pmount'),
] ]
@ -385,6 +384,15 @@ else:
print 'Extracting files to %s ...'%destdir print 'Extracting files to %s ...'%destdir
extract_tarball(f, destdir) extract_tarball(f, destdir)
mh = os.path.join(destdir, 'calibre-mount-helper')
if os.geteuid() == 0:
os.chown(mh, 0, 0)
os.chmod(mh,
stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
else:
print 'WARNING: Not running as root. Cannot install mount helper.',
print 'Device automounting may not work.'
pi = os.path.join(destdir, 'calibre_postinstall') pi = os.path.join(destdir, 'calibre_postinstall')
subprocess.call(pi, shell=True) subprocess.call(pi, shell=True)
return 0 return 0