mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
c5fbaf44f7
@ -60,6 +60,9 @@ def freeze():
|
|||||||
'/usr/lib/libgcrypt.so.11',
|
'/usr/lib/libgcrypt.so.11',
|
||||||
'/usr/lib/libgpg-error.so.0',
|
'/usr/lib/libgpg-error.so.0',
|
||||||
'/usr/lib/libphonon.so.4',
|
'/usr/lib/libphonon.so.4',
|
||||||
|
'/usr/lib/libssl.so.0.9.8',
|
||||||
|
'/usr/lib/libcrypto.so.0.9.8',
|
||||||
|
'/lib/libreadline.so.6',
|
||||||
]
|
]
|
||||||
|
|
||||||
binary_includes += [os.path.join(QTDIR, 'lib%s.so.4'%x) for x in QTDLLS]
|
binary_includes += [os.path.join(QTDIR, 'lib%s.so.4'%x) for x in QTDLLS]
|
||||||
|
@ -4,6 +4,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
''' Create an OSX installer '''
|
''' Create an OSX installer '''
|
||||||
|
|
||||||
import sys, re, os, shutil, subprocess, stat, glob, zipfile, plistlib
|
import sys, re, os, shutil, subprocess, stat, glob, zipfile, plistlib
|
||||||
|
sys.path = sys.path[1:]
|
||||||
l = {}
|
l = {}
|
||||||
exec open('setup.py').read() in l
|
exec open('setup.py').read() in l
|
||||||
VERSION = l['VERSION']
|
VERSION = l['VERSION']
|
||||||
@ -210,7 +211,6 @@ os.execv(python, args)
|
|||||||
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
|
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
|
||||||
|
|
||||||
|
|
||||||
self.add_plugins()
|
|
||||||
print 'Adding fontconfig'
|
print 'Adding fontconfig'
|
||||||
for f in glob.glob(os.path.expanduser('~/fontconfig-bundled/*')):
|
for f in glob.glob(os.path.expanduser('~/fontconfig-bundled/*')):
|
||||||
dest = os.path.join(frameworks_dir, os.path.basename(f))
|
dest = os.path.join(frameworks_dir, os.path.basename(f))
|
||||||
@ -222,6 +222,8 @@ os.execv(python, args)
|
|||||||
shutil.rmtree(dst)
|
shutil.rmtree(dst)
|
||||||
shutil.copytree('/usr/local/etc/fonts', dst, symlinks=False)
|
shutil.copytree('/usr/local/etc/fonts', dst, symlinks=False)
|
||||||
|
|
||||||
|
self.add_plugins()
|
||||||
|
|
||||||
print
|
print
|
||||||
print 'Adding IPython'
|
print 'Adding IPython'
|
||||||
dst = os.path.join(resource_dir, 'lib', 'python2.6', 'IPython')
|
dst = os.path.join(resource_dir, 'lib', 'python2.6', 'IPython')
|
||||||
|
138
installer/osx/py2app/launcher.c
Normal file
138
installer/osx/py2app/launcher.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
static const char *ERR_UNKNOWNPYTHONEXCEPTION = "An uncaught exception was raised during execution of the main script, but its class or name could not be determined";
|
||||||
|
|
||||||
|
static int
|
||||||
|
report_error(const char *msg) {
|
||||||
|
fprintf(stderr, msg);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fflush(stderr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These variable must be filled in before compiling
|
||||||
|
static const char *ENV_VARS[] = { /*ENV_VARS*/ NULL };
|
||||||
|
static const char *ENV_VAR_VALS[] = { /*ENV_VAR_VALS*/ NULL};
|
||||||
|
static char PROGRAM[] = "**PROGRAM**";
|
||||||
|
static const char MODULE[] = "**MODULE**";
|
||||||
|
|
||||||
|
#define EXE "@executable_path/.."
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_env_vars(const char* exe_path, const char* rpath) {
|
||||||
|
int i = 0;
|
||||||
|
char buf[3*PATH_MAX];
|
||||||
|
const char *env_var, *val;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
env_var = ENV_VARS[i];
|
||||||
|
if (env_var == NULL) break;
|
||||||
|
val = ENV_VAR_VALS[i++];
|
||||||
|
if (strstr(val, EXE) == val && strlen(val) >= strlen(EXE)+1) {
|
||||||
|
strncpy(buf, exe_path, 3*PATH_MAX-150);
|
||||||
|
strncpy(buf+strlen(exe_path), val+strlen(EXE), 150);
|
||||||
|
setenv(env_var, buf, 1);
|
||||||
|
} else
|
||||||
|
setenv(env_var, val, 1);
|
||||||
|
}
|
||||||
|
setenv("CALIBRE_LAUNCH_MODULE", MODULE, 1);
|
||||||
|
setenv("RESOURCEPATH", rpath, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char * const *argv, char * const *envp) {
|
||||||
|
char *pathPtr = NULL;
|
||||||
|
char buf[3*PATH_MAX];
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t buf_size = PATH_MAX+1;
|
||||||
|
char *ebuf = calloc(buf_size, sizeof(char));
|
||||||
|
ret = _NSGetExecutablePath(ebuf, &buf_size);
|
||||||
|
if (ret == -1) {
|
||||||
|
free(ebuf);
|
||||||
|
ebuf = calloc(buf_size, sizeof(char));
|
||||||
|
if (_NSGetExecutablePath(ebuf, &buf_size) != 0)
|
||||||
|
return report_error("Failed to find real path of executable.");
|
||||||
|
}
|
||||||
|
pathPtr = realpath(ebuf, buf);
|
||||||
|
if (pathPtr == NULL) {
|
||||||
|
return report_error(strerror(errno));
|
||||||
|
}
|
||||||
|
char *t;
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
t = rindex(pathPtr, '/');
|
||||||
|
if (t == NULL) return report_error("Failed to determine bundle path.");
|
||||||
|
*t = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
char rpath[PATH_MAX+1];
|
||||||
|
strncpy(rpath, pathPtr, strlen(pathPtr));
|
||||||
|
strncat(rpath, "/Contents/Resources", 50);
|
||||||
|
char exe_path[PATH_MAX+1];
|
||||||
|
strncpy(exe_path, pathPtr, strlen(pathPtr));
|
||||||
|
strncat(exe_path, "/Contents", 50);
|
||||||
|
|
||||||
|
set_env_vars(exe_path, rpath);
|
||||||
|
|
||||||
|
char main_script[PATH_MAX+1];
|
||||||
|
strncpy(main_script, rpath, strlen(rpath));
|
||||||
|
strncat(main_script, "/launcher.py", 20);
|
||||||
|
|
||||||
|
Py_SetProgramName(PROGRAM);
|
||||||
|
|
||||||
|
Py_Initialize();
|
||||||
|
|
||||||
|
char **argv_new = calloc(argc+1, sizeof(char *));
|
||||||
|
argv_new[argc] = NULL;
|
||||||
|
argv_new[0] = main_script;
|
||||||
|
memcpy(&argv_new[1], &argv[1], (argc - 1) * sizeof(char *));
|
||||||
|
PySys_SetArgv(argc, argv_new);
|
||||||
|
|
||||||
|
FILE *main_script_file = fopen(main_script, "r");
|
||||||
|
int rval = PyRun_SimpleFileEx(main_script_file, main_script, 1);
|
||||||
|
|
||||||
|
while (rval != 0) {
|
||||||
|
PyObject *exc, *exceptionClassName, *v, *exceptionName;
|
||||||
|
exc = PySys_GetObject("last_type");
|
||||||
|
|
||||||
|
if ( !exc ) {
|
||||||
|
rval = report_error(ERR_UNKNOWNPYTHONEXCEPTION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
exceptionClassName = PyObject_GetAttrString(exc, "__name__");
|
||||||
|
if (!exceptionClassName) {
|
||||||
|
rval = report_error(ERR_UNKNOWNPYTHONEXCEPTION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = PySys_GetObject("last_value");
|
||||||
|
exceptionName = (v ? PyObject_Str(v) : NULL);
|
||||||
|
|
||||||
|
char *class = PyString_AsString(exceptionClassName);
|
||||||
|
char *exception = "";
|
||||||
|
Py_DecRef(exceptionClassName);
|
||||||
|
if (exceptionName) {
|
||||||
|
exception = PyString_AsString(exceptionName);
|
||||||
|
Py_DecRef(exceptionName);
|
||||||
|
}
|
||||||
|
char msg[2000];
|
||||||
|
strncpy(msg, "An unexpected error occurred: ", 100);
|
||||||
|
strncpy(msg, class, 500);
|
||||||
|
strncpy(msg, " : ", 3);
|
||||||
|
strncpy(msg, exception, 500);
|
||||||
|
rval = report_error(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
Py_Finalize();
|
||||||
|
return rval;
|
||||||
|
}
|
@ -35,22 +35,24 @@ _recipes_pil_prescript(['Hdf5StubImagePlugin', 'FitsStubImagePlugin', 'SunImageP
|
|||||||
|
|
||||||
def _run():
|
def _run():
|
||||||
global __file__
|
global __file__
|
||||||
import os, sys, site
|
import os, sys
|
||||||
sys.frozen = 'macosx_app'
|
|
||||||
base = os.environ['RESOURCEPATH']
|
base = os.environ['RESOURCEPATH']
|
||||||
|
|
||||||
|
sys.frozen = 'macosx_app'
|
||||||
sys.frameworks_dir = os.path.join(os.path.dirname(base), 'Frameworks')
|
sys.frameworks_dir = os.path.join(os.path.dirname(base), 'Frameworks')
|
||||||
sys.new_app_bundle = True
|
sys.new_app_bundle = True
|
||||||
site.addsitedir(base)
|
sys.site_packages = os.path.join(base, 'Python', 'site-packages')
|
||||||
site.addsitedir(os.path.join(base, 'Python', 'site-packages'))
|
sys.binaries_path = os.path.join(os.path.dirname(base), 'MacOS')
|
||||||
|
sys.console_binaries_path = os.path.join(os.path.dirname(base),
|
||||||
|
'console.app', 'Contents', 'MacOS')
|
||||||
|
|
||||||
exe = os.environ.get('CALIBRE_LAUNCH_MODULE', 'calibre.gui2.main')
|
exe = os.environ.get('CALIBRE_LAUNCH_MODULE', 'calibre.gui2.main')
|
||||||
exe = os.path.join(base, 'Python', 'site-packages', *exe.split('.'))
|
exe = os.path.join(base, 'Python', 'site-packages', *exe.split('.'))
|
||||||
exe += '.py'
|
exe += '.py'
|
||||||
sys.argv[0] = __file__ = exe
|
sys.argv[0] = __file__ = exe
|
||||||
argv = os.environ.get('CALIBRE_LAUNCH_ARGV', None)
|
for arg in list(sys.argv[1:]):
|
||||||
if argv is not None:
|
if arg.startswith('-psn'):
|
||||||
import cPickle
|
sys.argv.remove(arg)
|
||||||
argv = cPickle.loads(argv)
|
|
||||||
sys.argv[1:] = argv
|
|
||||||
execfile(exe, globals(), globals())
|
execfile(exe, globals(), globals())
|
||||||
|
|
||||||
_run()
|
_run()
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
|
||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
|
||||||
__docformat__ = 'restructuredtext en'
|
|
||||||
|
|
||||||
|
|
||||||
import os, sys, cPickle
|
|
||||||
|
|
||||||
ENV = {}##ENV##
|
|
||||||
MODULE = ''##MODULE##
|
|
||||||
|
|
||||||
path = os.path.abspath(os.path.realpath(__file__))
|
|
||||||
dirpath = os.path.dirname(path)
|
|
||||||
name = os.path.basename(path)
|
|
||||||
base_dir = os.path.dirname(os.path.dirname(dirpath))
|
|
||||||
resources_dir = os.path.join(base_dir, 'Resources')
|
|
||||||
frameworks_dir = os.path.join(base_dir, 'Frameworks')
|
|
||||||
exe_dir = os.path.join(base_dir, 'MacOS')
|
|
||||||
base_name = os.path.splitext(name)[0]
|
|
||||||
python = os.path.join(base_dir, 'MacOS', 'Python')
|
|
||||||
|
|
||||||
for key, val in ENV.items():
|
|
||||||
if val.startswith('@exec'):
|
|
||||||
ENV[key] = os.path.normpath(val.replace('@executable_path', exe_dir))
|
|
||||||
ENV['CALIBRE_LAUNCH_MODULE'] = MODULE
|
|
||||||
ENV['CALIBRE_LAUNCH_ARGV'] = cPickle.dumps(sys.argv[1:], -1)
|
|
||||||
ENV['RESOURCEPATH'] = resources_dir
|
|
||||||
os.environ.update(ENV)
|
|
||||||
launcher = os.path.join(resources_dir, 'launcher.py')
|
|
||||||
args = ['-OO', launcher]
|
|
||||||
os.execv(python, args)
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -20,17 +20,50 @@ main_functions = l['main_functions']
|
|||||||
main_modules = l['main_modules']
|
main_modules = l['main_modules']
|
||||||
LICENSE = open('LICENSE', 'rb').read()
|
LICENSE = open('LICENSE', 'rb').read()
|
||||||
ENV = dict(
|
ENV = dict(
|
||||||
FC_CONFIG_DIR='@executable_path/../Resources/fonts',
|
|
||||||
MAGICK_HOME='@executable_path/../Frameworks/ImageMagick',
|
|
||||||
PYTHONDONTWRITEBYTECODE='1',
|
|
||||||
PYTHONIOENCODING='utf-8:replace',
|
|
||||||
PYTHONPATH='@executable_path/../Resources/Python/site-packages',
|
PYTHONPATH='@executable_path/../Resources/Python/site-packages',
|
||||||
PYTHONHOME='@executable_path/../Resources/Python',
|
PYTHONHOME='@executable_path/../Resources/Python',
|
||||||
|
FC_CONFIG_DIR='@executable_path/../Resources/fonts',
|
||||||
|
MAGICK_HOME='@executable_path/../Frameworks/ImageMagick',
|
||||||
|
QT_PLUGIN_PATH='@executable_path/../MacOS',
|
||||||
|
PYTHONDONTWRITEBYTECODE='1',
|
||||||
|
PYTHONIOENCODING='utf-8:replace',
|
||||||
PYTHONOPTIMIZE='2',
|
PYTHONOPTIMIZE='2',
|
||||||
QT_PLUGIN_PATH='@executable_path'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
SW = os.environ.get('SW')
|
SW = os.environ.get('SW', '/sw')
|
||||||
|
|
||||||
|
def compile_launchers(contents_dir, xprograms):
|
||||||
|
gcc = os.environ.get('CC', 'gcc')
|
||||||
|
base = os.path.dirname(__file__)
|
||||||
|
src = open(join(base, 'launcher.c'), 'rb').read()
|
||||||
|
env, env_vals = [], []
|
||||||
|
for key, val in ENV.items():
|
||||||
|
env.append('"%s"'% key)
|
||||||
|
env_vals.append('"%s"'% val)
|
||||||
|
env = ', '.join(env)+', '
|
||||||
|
env_vals = ', '.join(env_vals)+', '
|
||||||
|
src = src.replace('/*ENV_VARS*/', env)
|
||||||
|
src = src.replace('/*ENV_VAR_VALS*/', env_vals)
|
||||||
|
programs = []
|
||||||
|
for program, module in xprograms.items():
|
||||||
|
print '\tCompiling', program
|
||||||
|
out = join(contents_dir, 'MacOS', program)
|
||||||
|
programs.append(out)
|
||||||
|
psrc = src.replace('**PROGRAM**', program)
|
||||||
|
psrc = psrc.replace('**MODULE**', module)
|
||||||
|
fsrc = '/tmp/%s.c'%program
|
||||||
|
with open(fsrc, 'wb') as f:
|
||||||
|
f.write(psrc)
|
||||||
|
cmd = [gcc, '-Wall', '-arch', 'x86_64',
|
||||||
|
'-I%s/python/Python.framework/Headers'%SW,
|
||||||
|
fsrc, '-o', out, '-F%s/python'%SW,
|
||||||
|
'-framework', 'Python', '-framework', 'CoreFoundation',
|
||||||
|
'-headerpad_max_install_names']
|
||||||
|
print ' '.join(cmd)
|
||||||
|
sys.stdout.flush()
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
return programs
|
||||||
|
|
||||||
|
|
||||||
def flipwritable(fn, mode=None):
|
def flipwritable(fn, mode=None):
|
||||||
"""
|
"""
|
||||||
@ -43,6 +76,15 @@ def flipwritable(fn, mode=None):
|
|||||||
os.chmod(fn, stat.S_IWRITE | old_mode)
|
os.chmod(fn, stat.S_IWRITE | old_mode)
|
||||||
return old_mode
|
return old_mode
|
||||||
|
|
||||||
|
def thin(path):
|
||||||
|
try:
|
||||||
|
subprocess.check_call(['lipo', path, '-verify_arch', 'ppc64'])
|
||||||
|
print '\tThinning', path
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
subprocess.check_call(['lipo', path, '-thin', 'x86_64', '-output', path])
|
||||||
|
|
||||||
STRIPCMD = ['/usr/bin/strip', '-x', '-S', '-']
|
STRIPCMD = ['/usr/bin/strip', '-x', '-S', '-']
|
||||||
def strip_files(files, argv_max=(256 * 1024)):
|
def strip_files(files, argv_max=(256 * 1024)):
|
||||||
"""
|
"""
|
||||||
@ -120,8 +162,8 @@ class Py2App(object):
|
|||||||
|
|
||||||
self.copy_launcher_and_site()
|
self.copy_launcher_and_site()
|
||||||
self.create_exe()
|
self.create_exe()
|
||||||
|
self.thin_to_x86_64()
|
||||||
self.strip_files()
|
self.strip_files()
|
||||||
self.create_launchers()
|
|
||||||
|
|
||||||
ret = self.makedmg(self.build_dir, APPNAME+'-'+VERSION+'-x86_64')
|
ret = self.makedmg(self.build_dir, APPNAME+'-'+VERSION+'-x86_64')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
@ -134,23 +176,17 @@ class Py2App(object):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def create_launchers(self):
|
def thin_to_x86_64(self):
|
||||||
print '\nCreating launchers'
|
print '\nThinning to x86_64'
|
||||||
all_names = basenames['console'] + basenames['gui']
|
for y in (self.frameworks_dir, join(self.resources_dir, 'Python')):
|
||||||
all_modules = main_modules['console'] + main_modules['gui']
|
for x in os.walk(y):
|
||||||
launcher = join(os.path.dirname(__file__), 'loader.py')
|
for f in x[-1]:
|
||||||
launcher = open(launcher, 'rb').read()
|
f = join(x[0], f)
|
||||||
launcher = launcher.replace('{}##ENV##', repr(ENV))
|
if not os.path.isfile(f): continue
|
||||||
os.mkdir(join(self.resources_dir, 'loaders'))
|
for t in ('.so', '.dylib', '/Python'):
|
||||||
for basename, module in zip(all_names, all_modules):
|
if f.endswith(t):
|
||||||
py_file = join('src', *module.split('.'))+'.py'
|
thin(f)
|
||||||
shutil.copy2(py_file, join(self.resources_dir, 'Python',
|
break
|
||||||
'site-packages', *module.split('.'))+'.py')
|
|
||||||
raw = launcher.replace("''##MODULE##", repr(module))
|
|
||||||
path = join(self.resources_dir, 'loaders', basename)
|
|
||||||
open(path, 'wb').write(raw)
|
|
||||||
os.chmod(path, stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IREAD\
|
|
||||||
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def strip_files(self):
|
def strip_files(self):
|
||||||
@ -159,13 +195,19 @@ class Py2App(object):
|
|||||||
|
|
||||||
@flush
|
@flush
|
||||||
def create_exe(self):
|
def create_exe(self):
|
||||||
print '\nCreating executable'
|
print '\nCreating launchers'
|
||||||
gcc = os.environ.get('CC', 'gcc')
|
programs = {}
|
||||||
base = os.path.dirname(__file__)
|
for program, module in zip(basenames['console'],
|
||||||
out = join(self.contents_dir, 'MacOS', 'calibre')
|
main_modules['console'])+zip(basenames['gui'],
|
||||||
subprocess.check_call([gcc, '-Wall', '-arch', 'x86_64', join(base,
|
main_modules['gui']):
|
||||||
'main.c'), '-o', out])
|
programs[program] = module
|
||||||
self.to_strip.append(out)
|
programs = compile_launchers(self.contents_dir, programs)
|
||||||
|
for out in programs:
|
||||||
|
self.fix_dependencies_in_lib(out)
|
||||||
|
for module in main_modules['console'] + main_modules['gui']:
|
||||||
|
base = join(*module.split('.'))+'.py'
|
||||||
|
shutil.copy2(join('src', base),
|
||||||
|
join(self.resources_dir, 'Python', 'site-packages', base))
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def set_id(self, path_to_lib, new_id):
|
def set_id(self, path_to_lib, new_id):
|
||||||
@ -226,10 +268,6 @@ class Py2App(object):
|
|||||||
shutil.copy2(join(curr, 'Python'), currd)
|
shutil.copy2(join(curr, 'Python'), currd)
|
||||||
self.set_id(join(currd, 'Python'),
|
self.set_id(join(currd, 'Python'),
|
||||||
self.FID+'/Python.framework/Versions/%s/Python'%basename(curr))
|
self.FID+'/Python.framework/Versions/%s/Python'%basename(curr))
|
||||||
python = '%s/python/Python.framework/Versions/%s/Resources/Python.app/Contents/MacOS/Python'\
|
|
||||||
% (SW, self.version_info)
|
|
||||||
shutil.copy2(python, join(self.contents_dir, 'MacOS'))
|
|
||||||
self.fix_dependencies_in_lib(join(self.contents_dir, 'MacOS', 'Python'))
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_qt_frameworks(self):
|
def add_qt_frameworks(self):
|
||||||
@ -272,10 +310,16 @@ class Py2App(object):
|
|||||||
for f in glob.glob('src/calibre/plugins/*.so'):
|
for f in glob.glob('src/calibre/plugins/*.so'):
|
||||||
shutil.copy2(f, dest)
|
shutil.copy2(f, dest)
|
||||||
self.fix_dependencies_in_lib(join(dest, basename(f)))
|
self.fix_dependencies_in_lib(join(dest, basename(f)))
|
||||||
|
if 'podofo' in f:
|
||||||
|
self.change_dep('libpodofo.0.6.99.dylib',
|
||||||
|
self.FID+'/'+'libpodofo.0.6.99.dylib', join(dest, basename(f)))
|
||||||
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def create_plist(self):
|
def create_plist(self):
|
||||||
|
env = dict(**ENV)
|
||||||
|
env['CALIBRE_LAUNCHED_FROM_BUNDLE']='1';
|
||||||
|
|
||||||
pl = dict(
|
pl = dict(
|
||||||
CFBundleDevelopmentRegion='English',
|
CFBundleDevelopmentRegion='English',
|
||||||
CFBundleDisplayName=APPNAME,
|
CFBundleDisplayName=APPNAME,
|
||||||
@ -286,7 +330,6 @@ class Py2App(object):
|
|||||||
CFBundleSignature='????',
|
CFBundleSignature='????',
|
||||||
CFBundleExecutable='calibre',
|
CFBundleExecutable='calibre',
|
||||||
LSMinimumSystemVersion='10.5.2',
|
LSMinimumSystemVersion='10.5.2',
|
||||||
PyRuntimeLocations=[self.FID+'/Python.framework/Versions/%s/Python'%self.version_info],
|
|
||||||
LSRequiresNativeExecution=True,
|
LSRequiresNativeExecution=True,
|
||||||
NSAppleScriptEnabled=False,
|
NSAppleScriptEnabled=False,
|
||||||
NSHumanReadableCopyright='Copyright 2008, Kovid Goyal',
|
NSHumanReadableCopyright='Copyright 2008, Kovid Goyal',
|
||||||
@ -294,7 +337,7 @@ class Py2App(object):
|
|||||||
'application. Visit http://calibre.kovidgoyal.net for details.'),
|
'application. Visit http://calibre.kovidgoyal.net for details.'),
|
||||||
CFBundleIconFile='library.icns',
|
CFBundleIconFile='library.icns',
|
||||||
LSMultipleInstancesProhibited=True,
|
LSMultipleInstancesProhibited=True,
|
||||||
LSEnvironment=ENV
|
LSEnvironment=env
|
||||||
)
|
)
|
||||||
plistlib.writePlist(pl, join(self.contents_dir, 'Info.plist'))
|
plistlib.writePlist(pl, join(self.contents_dir, 'Info.plist'))
|
||||||
|
|
||||||
@ -374,7 +417,7 @@ class Py2App(object):
|
|||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_misc_libraries(self):
|
def add_misc_libraries(self):
|
||||||
for x in ('usb', 'unrar'):
|
for x in ('usb', 'unrar', 'readline.6.0'):
|
||||||
print '\nAdding', x
|
print '\nAdding', x
|
||||||
x = 'lib%s.dylib'%x
|
x = 'lib%s.dylib'%x
|
||||||
shutil.copy2(join(SW, 'lib', x), self.frameworks_dir)
|
shutil.copy2(join(SW, 'lib', x), self.frameworks_dir)
|
||||||
@ -551,9 +594,16 @@ class Py2App(object):
|
|||||||
print '\nInstaller size: %.2fMB\n'%size
|
print '\nInstaller size: %.2fMB\n'%size
|
||||||
return dmg
|
return dmg
|
||||||
|
|
||||||
|
def test_exe():
|
||||||
|
build_dir = abspath(join('build', APPNAME+'.app'))
|
||||||
|
py2app = Py2App(build_dir)
|
||||||
|
py2app.create_exe()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
if 'test_exe' in sys.argv:
|
||||||
|
return test_exe()
|
||||||
build_dir = abspath(join('build', APPNAME+'.app'))
|
build_dir = abspath(join('build', APPNAME+'.app'))
|
||||||
if os.path.exists(build_dir):
|
if os.path.exists(build_dir):
|
||||||
shutil.rmtree(build_dir)
|
shutil.rmtree(build_dir)
|
||||||
|
29
setup.py
29
setup.py
@ -73,22 +73,29 @@ if __name__ == '__main__':
|
|||||||
upload_to_pypi, stage3, stage2, stage1, upload, \
|
upload_to_pypi, stage3, stage2, stage1, upload, \
|
||||||
upload_rss, betas, build_linux32, build_linux64, \
|
upload_rss, betas, build_linux32, build_linux64, \
|
||||||
build_osx64
|
build_osx64
|
||||||
resources.SCRIPTS = list(basenames['console']+basenames['gui'])
|
resources.SCRIPTS = {}
|
||||||
|
for x in ('console', 'gui'):
|
||||||
|
for name in basenames[x]:
|
||||||
|
resources.SCRIPTS[name] = x
|
||||||
|
|
||||||
|
list(basenames['console']+basenames['gui'])
|
||||||
|
|
||||||
entry_points['console_scripts'].append(
|
entry_points['console_scripts'].append(
|
||||||
'calibre_postinstall = calibre.linux:post_install')
|
'calibre_postinstall = calibre.linux:post_install')
|
||||||
optional = []
|
optional = []
|
||||||
def qmake_query(arg=''):
|
def qmake_query(arg=''):
|
||||||
return subprocess.Popen([QMAKE, '-query', arg],
|
cmd = [QMAKE, '-query']
|
||||||
stdout=subprocess.PIPE).stdout.read()
|
if arg:
|
||||||
|
cmd += [arg]
|
||||||
|
return subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read()
|
||||||
qt_inc = qt_lib = None
|
qt_inc = qt_lib = None
|
||||||
qt_inc = qmake_query('QT_INSTALL_HEADERS').splitlines()[0]
|
qt_inc = qmake_query('QT_INSTALL_HEADERS').splitlines()[0]
|
||||||
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:
|
if qt_lib is None or qt_inc is None:
|
||||||
print 'WARNING: Could not find QT librariers and headers.',
|
print '\n\nWARNING: Could not find QT librariers and headers.',
|
||||||
print 'Is qmake in your PATH?'
|
print 'Is qmake in your PATH?\n\n'
|
||||||
|
|
||||||
|
|
||||||
if iswindows:
|
if iswindows:
|
||||||
@ -121,9 +128,9 @@ if __name__ == '__main__':
|
|||||||
poppler_lib), qt_lib],
|
poppler_lib), qt_lib],
|
||||||
include_dirs=[poppler_inc, qt_inc]))
|
include_dirs=[poppler_inc, qt_inc]))
|
||||||
else:
|
else:
|
||||||
print 'WARNING: Poppler not found on your system. Various PDF related',
|
print '\n\nWARNING: Poppler not found on your system. Various PDF related',
|
||||||
print 'functionality will not work. Use the POPPLER_INC_DIR and',
|
print 'functionality will not work. Use the POPPLER_INC_DIR and',
|
||||||
print 'POPPLER_LIB_DIR environment variables.'
|
print 'POPPLER_LIB_DIR environment variables.\n\n'
|
||||||
|
|
||||||
podofo_inc = '/usr/include/podofo' if islinux else \
|
podofo_inc = '/usr/include/podofo' if islinux else \
|
||||||
'C:\\podofo\\include\\podofo' if iswindows else \
|
'C:\\podofo\\include\\podofo' if iswindows else \
|
||||||
@ -138,9 +145,9 @@ if __name__ == '__main__':
|
|||||||
library_dirs=[os.environ.get('PODOFO_LIB_DIR', podofo_lib)],
|
library_dirs=[os.environ.get('PODOFO_LIB_DIR', podofo_lib)],
|
||||||
include_dirs=[podofo_inc]))
|
include_dirs=[podofo_inc]))
|
||||||
else:
|
else:
|
||||||
print 'WARNING: PoDoFo not found on your system. Various PDF related',
|
print '\n\nWARNING: PoDoFo not found on your system. Various PDF related',
|
||||||
print 'functionality will not work. Use the PODOFO_INC_DIR and',
|
print 'functionality will not work. Use the PODOFO_INC_DIR and',
|
||||||
print 'PODOFO_LIB_DIR environment variables.'
|
print 'PODOFO_LIB_DIR environment variables.\n\n'
|
||||||
|
|
||||||
fc_inc = '/usr/include/fontconfig' if islinux else \
|
fc_inc = '/usr/include/fontconfig' if islinux else \
|
||||||
r'C:\cygwin\home\kovid\fontconfig\include\fontconfig' if iswindows else \
|
r'C:\cygwin\home\kovid\fontconfig\include\fontconfig' if iswindows else \
|
||||||
@ -152,8 +159,8 @@ if __name__ == '__main__':
|
|||||||
fc_inc = os.environ.get('FC_INC_DIR', fc_inc)
|
fc_inc = os.environ.get('FC_INC_DIR', fc_inc)
|
||||||
fc_lib = os.environ.get('FC_LIB_DIR', fc_lib)
|
fc_lib = os.environ.get('FC_LIB_DIR', fc_lib)
|
||||||
if not os.path.exists(os.path.join(fc_inc, 'fontconfig.h')):
|
if not os.path.exists(os.path.join(fc_inc, 'fontconfig.h')):
|
||||||
print 'ERROR: fontconfig not found on your system.',
|
print '\n\nERROR: fontconfig not found on your system.',
|
||||||
print 'Use the FC_INC_DIR and FC_LIB_DIR environment variables.'
|
print 'Use the FC_INC_DIR and FC_LIB_DIR environment variables.\n\n'
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
ext_modules = optional + [
|
ext_modules = optional + [
|
||||||
|
|
||||||
|
@ -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.6.10'
|
__version__ = '0.6.11'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -6,7 +6,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
Embedded console for debugging.
|
Embedded console for debugging.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import sys, os, re
|
import sys, os, re, shutil
|
||||||
from calibre.utils.config import OptionParser
|
from calibre.utils.config import OptionParser
|
||||||
from calibre.constants import iswindows, isosx
|
from calibre.constants import iswindows, isosx
|
||||||
from calibre.libunzip import update
|
from calibre.libunzip import update
|
||||||
@ -45,6 +45,9 @@ def update_zipfile(zipfile, mod, path):
|
|||||||
name = mod.replace('.', '/') + os.path.splitext(path)[-1]
|
name = mod.replace('.', '/') + os.path.splitext(path)[-1]
|
||||||
update(zipfile, [pat], [path], [name])
|
update(zipfile, [pat], [path], [name])
|
||||||
|
|
||||||
|
def update_site_packages(sp, mod, path):
|
||||||
|
dest = os.path.join(sp, *mod.split('.'))+'.py'
|
||||||
|
shutil.copy2(path, dest)
|
||||||
|
|
||||||
def update_module(mod, path):
|
def update_module(mod, path):
|
||||||
if not hasattr(sys, 'frozen'):
|
if not hasattr(sys, 'frozen'):
|
||||||
@ -52,6 +55,8 @@ def update_module(mod, path):
|
|||||||
zp = None
|
zp = None
|
||||||
if iswindows:
|
if iswindows:
|
||||||
zp = os.path.join(os.path.dirname(sys.executable), 'library.zip')
|
zp = os.path.join(os.path.dirname(sys.executable), 'library.zip')
|
||||||
|
elif getattr(sys, 'new_app_bundle', False):
|
||||||
|
update_site_packages(sys.site_packages, mod, path)
|
||||||
elif isosx:
|
elif isosx:
|
||||||
zp = os.path.join(os.path.dirname(getattr(sys, 'frameworks_dir')),
|
zp = os.path.join(os.path.dirname(getattr(sys, 'frameworks_dir')),
|
||||||
'Resources', 'lib',
|
'Resources', 'lib',
|
||||||
|
@ -38,7 +38,7 @@ class PRS505(CLI, Device):
|
|||||||
WINDOWS_CARD_A_MEM = re.compile(r'PRS-505/\S+:MS')
|
WINDOWS_CARD_A_MEM = re.compile(r'PRS-505/\S+:MS')
|
||||||
WINDOWS_CARD_B_MEM = re.compile(r'PRS-505/\S+:SD')
|
WINDOWS_CARD_B_MEM = re.compile(r'PRS-505/\S+:SD')
|
||||||
|
|
||||||
OSX_MAIN_MEM = re.compile(r'Sony PRS-(505|300)/[^:]+ Media')
|
OSX_MAIN_MEM = re.compile(r'Sony PRS-(((505|300)/[^:]+)|(300)) Media')
|
||||||
OSX_CARD_A_MEM = re.compile(r'Sony PRS-505/[^:]+:MS Media')
|
OSX_CARD_A_MEM = re.compile(r'Sony PRS-505/[^:]+:MS Media')
|
||||||
OSX_CARD_B_MEM = re.compile(r'Sony PRS-505/[^:]+:SD Media')
|
OSX_CARD_B_MEM = re.compile(r'Sony PRS-505/[^:]+:SD Media')
|
||||||
|
|
||||||
@ -55,6 +55,7 @@ class PRS505(CLI, Device):
|
|||||||
EBOOK_DIR_MAIN = 'database/media/books'
|
EBOOK_DIR_MAIN = 'database/media/books'
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
|
self.report_progress = lambda x, y: x
|
||||||
Device.open(self)
|
Device.open(self)
|
||||||
|
|
||||||
def write_cache(prefix):
|
def write_cache(prefix):
|
||||||
|
@ -21,12 +21,12 @@ class PRS700(PRS505):
|
|||||||
|
|
||||||
BCD = [0x31a]
|
BCD = [0x31a]
|
||||||
|
|
||||||
WINDOWS_MAIN_MEM = re.compile('PRS-[67]00')
|
WINDOWS_MAIN_MEM = re.compile('PRS-((700/)|(600&))')
|
||||||
WINDOWS_CARD_A_MEM = re.compile(r'PRS-[67]00/\S+:MS')
|
WINDOWS_CARD_A_MEM = re.compile(r'PRS-((700/\S+:)|(600_))MS')
|
||||||
WINDOWS_CARD_B_MEM = re.compile(r'PRS-[67]00/\S+:SD')
|
WINDOWS_CARD_B_MEM = re.compile(r'PRS-((700/\S+:)|(600_))SD')
|
||||||
|
|
||||||
OSX_MAIN_MEM = re.compile(r'Sony PRS-[67]00/[^:]+ Media')
|
OSX_MAIN_MEM = re.compile(r'Sony PRS-((700/[^:]+)|(600)) Media')
|
||||||
OSX_CARD_A_MEM = re.compile(r'Sony PRS-[67]00/[^:]+:MS Media')
|
OSX_CARD_A_MEM = re.compile(r'Sony PRS-((700/[^:]+:)|(600 ))MS Media')
|
||||||
OSX_CARD_B_MEM = re.compile(r'Sony PRS-[67]00/[^:]+:SD Media')
|
OSX_CARD_B_MEM = re.compile(r'Sony PRS-((700/[^:]+:)|(600 ))SD Media')
|
||||||
|
|
||||||
|
|
||||||
|
@ -814,7 +814,6 @@ OptionRecommendation(name='language',
|
|||||||
out_dir = os.path.join(self.opts.debug_pipeline, 'processed')
|
out_dir = os.path.join(self.opts.debug_pipeline, 'processed')
|
||||||
self.dump_oeb(self.oeb, out_dir)
|
self.dump_oeb(self.oeb, out_dir)
|
||||||
self.log('Processed HTML written to:', out_dir)
|
self.log('Processed HTML written to:', out_dir)
|
||||||
return
|
|
||||||
|
|
||||||
self.log.info('Creating %s...'%self.output_plugin.name)
|
self.log.info('Creating %s...'%self.output_plugin.name)
|
||||||
our = CompositeProgressReporter(0.67, 1., self.ui_reporter)
|
our = CompositeProgressReporter(0.67, 1., self.ui_reporter)
|
||||||
|
@ -127,6 +127,7 @@ class Stylizer(object):
|
|||||||
if elem.tag == XHTML('style') and elem.text \
|
if elem.tag == XHTML('style') and elem.text \
|
||||||
and elem.get('type', CSS_MIME) in OEB_STYLES:
|
and elem.get('type', CSS_MIME) in OEB_STYLES:
|
||||||
text = XHTML_CSS_NAMESPACE + elem.text
|
text = XHTML_CSS_NAMESPACE + elem.text
|
||||||
|
text = oeb.css_preprocessor(text)
|
||||||
stylesheet = parser.parseString(text, href=cssname)
|
stylesheet = parser.parseString(text, href=cssname)
|
||||||
stylesheet.namespaces['h'] = XHTML_NS
|
stylesheet.namespaces['h'] = XHTML_NS
|
||||||
stylesheets.append(stylesheet)
|
stylesheets.append(stylesheet)
|
||||||
|
@ -23,7 +23,8 @@ class TXTInput(InputFormatPlugin):
|
|||||||
'With this option it will assume that every line represents '
|
'With this option it will assume that every line represents '
|
||||||
'a paragraph instead.')),
|
'a paragraph instead.')),
|
||||||
OptionRecommendation(name='markdown', recommended_value=False,
|
OptionRecommendation(name='markdown', recommended_value=False,
|
||||||
help=_('Run the text input though the markdown processor.')),
|
help=_('Run the text input through the markdown pre-processor. To '
|
||||||
|
'learn more about markdown see')+' http://daringfireball.net/projects/markdown/'),
|
||||||
])
|
])
|
||||||
|
|
||||||
def convert(self, stream, options, file_ext, log,
|
def convert(self, stream, options, file_ext, log,
|
||||||
|
@ -464,9 +464,16 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
def create_symlinks(self):
|
def create_symlinks(self):
|
||||||
from calibre.utils.osx_symlinks import create_symlinks
|
from calibre.utils.osx_symlinks import create_symlinks
|
||||||
loc, paths = create_symlinks()
|
loc, paths = create_symlinks()
|
||||||
info_dialog(self, _('Command line tools installed'),
|
if loc is None:
|
||||||
_('Command line tools installed in')+' '+loc,
|
error_dialog(self, _('Error'),
|
||||||
det_msg=paths, show=True)
|
_('Failed to install command line tools.'),
|
||||||
|
det_msg=paths, show=True)
|
||||||
|
else:
|
||||||
|
info_dialog(self, _('Command line tools installed'),
|
||||||
|
'<p>'+_('Command line tools installed in')+' '+loc+
|
||||||
|
'<br>'+ _('If you move calibre.app, you have to re-install '
|
||||||
|
'the command line tools.'),
|
||||||
|
det_msg='\n'.join(paths), show=True)
|
||||||
|
|
||||||
def setup_conversion_options(self):
|
def setup_conversion_options(self):
|
||||||
self.conversion_options = ConfigTabs(self)
|
self.conversion_options = ConfigTabs(self)
|
||||||
|
@ -699,10 +699,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="compact_button">
|
<widget class="QPushButton" name="compact_button">
|
||||||
<property name="toolTip">
|
|
||||||
<string>Free unused diskspace from the database</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Check database integrity</string>
|
<string>&Check database integrity</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -122,21 +122,49 @@ class TagsModel(QStandardItemModel):
|
|||||||
self._data[category], self.cmap[r], self.bold_font, self.icon_map))
|
self._data[category], self.cmap[r], self.bold_font, self.icon_map))
|
||||||
#self.reset()
|
#self.reset()
|
||||||
|
|
||||||
|
def reset_all_states(self):
|
||||||
|
changed_indices = []
|
||||||
|
for category in self._data.values():
|
||||||
|
Category = self.find_category(category)
|
||||||
|
for tag in category:
|
||||||
|
if tag.state != 0:
|
||||||
|
tag.state = 0
|
||||||
|
if Category is not None:
|
||||||
|
Tag = self.find_tag(tag, Category)
|
||||||
|
if Tag is not None:
|
||||||
|
changed_indices.append(Tag.index())
|
||||||
|
for idx in changed_indices:
|
||||||
|
if idx.isValid():
|
||||||
|
self.emit(SIGNAL('dataChanged(QModelIndex,QModelIndex)'),
|
||||||
|
idx, idx)
|
||||||
|
|
||||||
def clear_state(self):
|
def clear_state(self):
|
||||||
for category in self._data.values():
|
for category in self._data.values():
|
||||||
for tag in category:
|
for tag in category:
|
||||||
tag.state = 0
|
tag.state = 0
|
||||||
self.refresh()
|
self.reset_all_states()
|
||||||
|
|
||||||
|
def find_category(self, name):
|
||||||
|
root = self.invisibleRootItem()
|
||||||
|
for i in range(root.rowCount()):
|
||||||
|
child = root.child(i)
|
||||||
|
if getattr(child, 'category', None) == name:
|
||||||
|
return child
|
||||||
|
|
||||||
|
def find_tag(self, tag, category):
|
||||||
|
for i in range(category.rowCount()):
|
||||||
|
child = category.child(i)
|
||||||
|
if getattr(child, 'tag', None) == tag:
|
||||||
|
return child
|
||||||
|
|
||||||
|
|
||||||
def reinit(self, *args, **kwargs):
|
def reinit(self, *args, **kwargs):
|
||||||
if self.ignore_next_search == 0:
|
if self.ignore_next_search == 0:
|
||||||
for category in self._data.values():
|
self.reset_all_states()
|
||||||
for tag in category:
|
|
||||||
tag.state = 0
|
|
||||||
self.reset()
|
|
||||||
else:
|
else:
|
||||||
self.ignore_next_search -= 1
|
self.ignore_next_search -= 1
|
||||||
|
|
||||||
|
|
||||||
def toggle(self, index):
|
def toggle(self, index):
|
||||||
if index.parent().isValid():
|
if index.parent().isValid():
|
||||||
category = self.row_map[index.parent().row()]
|
category = self.row_map[index.parent().row()]
|
||||||
|
@ -42,8 +42,8 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, out_format
|
|||||||
result = d.exec_()
|
result = d.exec_()
|
||||||
|
|
||||||
if result == QDialog.Accepted:
|
if result == QDialog.Accepted:
|
||||||
if not convert_existing(parent, db, [book_id], d.output_format):
|
#if not convert_existing(parent, db, [book_id], d.output_format):
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
mi = db.get_metadata(book_id, True)
|
mi = db.get_metadata(book_id, True)
|
||||||
in_file = db.format_abspath(book_id, d.input_format, True)
|
in_file = db.format_abspath(book_id, d.input_format, True)
|
||||||
@ -198,7 +198,10 @@ def convert_existing(parent, db, book_ids, output_format):
|
|||||||
already_converted_ids.append(book_id)
|
already_converted_ids.append(book_id)
|
||||||
already_converted_titles.append(db.get_metadata(book_id, True).title)
|
already_converted_titles.append(db.get_metadata(book_id, True).title)
|
||||||
|
|
||||||
if not question_dialog(parent, _('Convert existing'), _('The following books have already been converted to %s format. Do you wish to reconvert them?' % output_format), '\n'.join(already_converted_titles)):
|
if not question_dialog(parent, _('Convert existing'),
|
||||||
|
_('The following books have already been converted to %s format. '
|
||||||
|
'Do you wish to reconvert them?') % output_format,
|
||||||
|
'\n'.join(already_converted_titles)):
|
||||||
book_ids = [x for x in book_ids if x not in already_converted_ids]
|
book_ids = [x for x in book_ids if x not in already_converted_ids]
|
||||||
|
|
||||||
return book_ids
|
return book_ids
|
||||||
|
@ -114,6 +114,24 @@ class LibraryServer(object):
|
|||||||
</entry>
|
</entry>
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
STANZA_TAG_ENTRY=MarkupTemplate(textwrap.dedent('''\
|
||||||
|
<entry xmlns:py="http://genshi.edgewall.org/">
|
||||||
|
<title>${tags}</title>
|
||||||
|
<id>urn:calibre:${record[FM['id']]}</id>
|
||||||
|
<updated>${timestamp}</updated>
|
||||||
|
<link type="application/atom+xml" href="/stanza/?tagid=${record[FM['id']]}" />
|
||||||
|
</entry>
|
||||||
|
'''))
|
||||||
|
|
||||||
|
STANZA_SERIES_ENTRY=MarkupTemplate(textwrap.dedent('''\
|
||||||
|
<entry xmlns:py="http://genshi.edgewall.org/">
|
||||||
|
<title>${series}</title>
|
||||||
|
<id>urn:calibre:${record[FM['id']]}</id>
|
||||||
|
<updated>${timestamp}</updated>
|
||||||
|
<link type="application/atom+xml" href="/stanza/?seriesid=${record[FM['id']]}" />
|
||||||
|
</entry>
|
||||||
|
'''))
|
||||||
|
|
||||||
STANZA = MarkupTemplate(textwrap.dedent('''\
|
STANZA = MarkupTemplate(textwrap.dedent('''\
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:py="http://genshi.edgewall.org/">
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:py="http://genshi.edgewall.org/">
|
||||||
@ -166,6 +184,18 @@ class LibraryServer(object):
|
|||||||
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
||||||
<link type="application/atom+xml" href="/stanza/?sortby=bynewest" />
|
<link type="application/atom+xml" href="/stanza/?sortby=bynewest" />
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<title>By Tag</title>
|
||||||
|
<id>urn:uuid:824921e8-db8a-4e61-7d38-f1ce41502853</id>
|
||||||
|
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
||||||
|
<link type="application/atom+xml" href="/stanza/?sortby=bytag" />
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<title>By Series</title>
|
||||||
|
<id>urn:uuid:512a5e50-a88f-f6b8-82aa-8f129c719f61</id>
|
||||||
|
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
||||||
|
<link type="application/atom+xml" href="/stanza/?sortby=byseries" />
|
||||||
|
</entry>
|
||||||
</feed>
|
</feed>
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
@ -339,30 +369,46 @@ class LibraryServer(object):
|
|||||||
|
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
def stanza(self, search=None, sortby=None, authorid=None):
|
def stanza(self, search=None, sortby=None, authorid=None, tagid=None, seriesid=None):
|
||||||
'Feeds to read calibre books on a ipod with stanza.'
|
'Feeds to read calibre books on a ipod with stanza.'
|
||||||
books = []
|
books = []
|
||||||
updated = self.db.last_modified()
|
updated = self.db.last_modified()
|
||||||
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
|
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
|
||||||
cherrypy.response.headers['Content-Type'] = 'text/xml'
|
cherrypy.response.headers['Content-Type'] = 'text/xml'
|
||||||
if not sortby and not search and not authorid:
|
if not sortby and not search and not authorid and not tagid and not seriesid:
|
||||||
return self.STANZA_MAIN.generate(subtitle='', data=books, FM=FIELD_MAP,
|
return self.STANZA_MAIN.generate(subtitle='', data=books, FM=FIELD_MAP,
|
||||||
updated=updated, id='urn:calibre:main').render('xml')
|
updated=updated, id='urn:calibre:main').render('xml')
|
||||||
if authorid:
|
if authorid:
|
||||||
authorid=int(authorid)
|
authorid=int(authorid)
|
||||||
au = self.db.authors(authorid, index_is_id=True)
|
au = self.db.authors(authorid, index_is_id=True)
|
||||||
ids = self.db.data.get_matches('authors', au)
|
ids = self.db.data.get_matches('authors', au)
|
||||||
|
elif tagid:
|
||||||
|
tagid=int(tagid)
|
||||||
|
ta = self.db.tags(tagid, index_is_id=True)
|
||||||
|
ids = self.db.data.get_matches('tags', ta)
|
||||||
|
elif seriesid:
|
||||||
|
seriesid=int(seriesid)
|
||||||
|
se = self.db.series(seriesid, index_is_id=True)
|
||||||
|
ids = self.db.data.get_matches('series', se)
|
||||||
else:
|
else:
|
||||||
ids = self.db.data.parse(search) if search and search.strip() else self.db.data.universal_set()
|
ids = self.db.data.parse(search) if search and search.strip() else self.db.data.universal_set()
|
||||||
record_list = list(iter(self.db))
|
record_list = list(iter(self.db))
|
||||||
if sortby == "byauthor":
|
if sortby == "byauthor":
|
||||||
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['author_sort']], y[FIELD_MAP['author_sort']]))
|
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['author_sort']], y[FIELD_MAP['author_sort']]))
|
||||||
elif sortby == "bytitle" or authorid:
|
elif sortby == "bytag":
|
||||||
|
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['tags']], y[FIELD_MAP['tags']]))
|
||||||
|
elif sortby == "byseries":
|
||||||
|
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['series']], y[FIELD_MAP['series']]))
|
||||||
|
elif sortby == "bytitle" or authorid or tagid:
|
||||||
record_list.sort(lambda x, y: cmp(title_sort(x[FIELD_MAP['title']]),
|
record_list.sort(lambda x, y: cmp(title_sort(x[FIELD_MAP['title']]),
|
||||||
title_sort(y[FIELD_MAP['title']])))
|
title_sort(y[FIELD_MAP['title']])))
|
||||||
|
elif seriesid:
|
||||||
|
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['series_index']], y[FIELD_MAP['series_index']]))
|
||||||
else:
|
else:
|
||||||
record_list = reversed(record_list)
|
record_list = reversed(record_list)
|
||||||
author_list=[]
|
author_list=[]
|
||||||
|
tag_list=[]
|
||||||
|
series_list=[]
|
||||||
for record in record_list:
|
for record in record_list:
|
||||||
if record[0] not in ids: continue
|
if record[0] not in ids: continue
|
||||||
r = record[FIELD_MAP['formats']]
|
r = record[FIELD_MAP['formats']]
|
||||||
@ -401,6 +447,30 @@ class LibraryServer(object):
|
|||||||
fmt=fmt,
|
fmt=fmt,
|
||||||
timestamp=strftime('%Y-%m-%dT%H:%M:%S+00:00', record[5]),
|
timestamp=strftime('%Y-%m-%dT%H:%M:%S+00:00', record[5]),
|
||||||
).render('xml').decode('utf8'))
|
).render('xml').decode('utf8'))
|
||||||
|
elif sortby == "bytag":
|
||||||
|
if tags and tags not in tag_list:
|
||||||
|
tag_list.append(tags)
|
||||||
|
books.append(self.STANZA_TAG_ENTRY.generate(
|
||||||
|
tags=tags,
|
||||||
|
record=record, FM=FIELD_MAP,
|
||||||
|
port=self.opts.port,
|
||||||
|
extra=''.join(extra),
|
||||||
|
mimetype=mimetype,
|
||||||
|
fmt=fmt,
|
||||||
|
timestamp=strftime('%Y-%m-%dT%H:%M:%S+00:00', record[5]),
|
||||||
|
).render('xml').decode('utf8'))
|
||||||
|
elif sortby == "byseries":
|
||||||
|
if series and series not in series_list:
|
||||||
|
series_list.append(series)
|
||||||
|
books.append(self.STANZA_SERIES_ENTRY.generate(
|
||||||
|
series=series,
|
||||||
|
record=record, FM=FIELD_MAP,
|
||||||
|
port=self.opts.port,
|
||||||
|
extra=''.join(extra),
|
||||||
|
mimetype=mimetype,
|
||||||
|
fmt=fmt,
|
||||||
|
timestamp=strftime('%Y-%m-%dT%H:%M:%S+00:00', record[5]),
|
||||||
|
).render('xml').decode('utf8'))
|
||||||
else:
|
else:
|
||||||
books.append(self.STANZA_ENTRY.generate(
|
books.append(self.STANZA_ENTRY.generate(
|
||||||
authors=authors,
|
authors=authors,
|
||||||
@ -415,6 +485,7 @@ class LibraryServer(object):
|
|||||||
return self.STANZA.generate(subtitle='', data=books, FM=FIELD_MAP,
|
return self.STANZA.generate(subtitle='', data=books, FM=FIELD_MAP,
|
||||||
updated=updated, id='urn:calibre:main').render('xml')
|
updated=updated, id='urn:calibre:main').render('xml')
|
||||||
|
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
def library(self, start='0', num='50', sort=None, search=None,
|
def library(self, start='0', num='50', sort=None, search=None,
|
||||||
_=None, order='ascending'):
|
_=None, order='ascending'):
|
||||||
@ -465,7 +536,8 @@ class LibraryServer(object):
|
|||||||
cherrypy.request.headers.get('Stanza-Device-Name', 919) != 919 or \
|
cherrypy.request.headers.get('Stanza-Device-Name', 919) != 919 or \
|
||||||
cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 or \
|
cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 or \
|
||||||
ua.startswith('Stanza')
|
ua.startswith('Stanza')
|
||||||
return self.stanza(search=kwargs.get('search', None), sortby=kwargs.get('sortby',None), authorid=kwargs.get('authorid',None)) if want_opds else self.static('index.html')
|
return self.stanza(search=kwargs.get('search', None), sortby=kwargs.get('sortby',None), authorid=kwargs.get('authorid',None),
|
||||||
|
tagid=kwargs.get('tagid',None), seriesid=kwargs.get('seriesid',None)) if want_opds else self.static('index.html')
|
||||||
|
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="count_bar">
|
<div id="count_bar">
|
||||||
<span id="left"><img src="/static/first.png" alt="Show first set of books" title="Show first set of books"/> <img src="/static/previous.png" alt="Show previous set of books" title="Show previous set of books"/> </span><span id="count"> </span> <span id="right"><img src="/static/next.png" alt="Show first set of books" title="Show first set of books"/> <img src="/static/last.png" alt="Show previous set of books" title="Show previous set of books" /></span>
|
<span id="left"><img src="/static/first.png" alt="Show first set of books" title="Show first set of books"/> <img src="/static/previous.png" alt="Show previous set of books" title="Show previous set of books"/> </span><span id="count"> </span> <span id="right"><img src="/static/next.png" alt="Show next set of books" title="Show next set of books"/> <img src="/static/last.png" alt="Show last set of books" title="Show last set of books" /></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="main">
|
<div id="main">
|
||||||
|
@ -78,7 +78,7 @@ Device Integration
|
|||||||
|
|
||||||
What devices does |app| support?
|
What devices does |app| support?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
At the moment |app| has full support for the SONY PRS 500/505/700, Cybook Gen 3/Opus, Amazon Kindle 1/2/DX, Netronix EB600, Ectaco Jetbook, BeBook/BeBook Mini, Irex Illiad/DR1000, Adroid phones and the iPhone. In addition, using the :guilabel:`Save to disk` function you can use it with any ebook reader that exports itself as a USB disk.
|
At the moment |app| has full support for the SONY PRS 300/500/505/600/700, Cybook Gen 3/Opus, Amazon Kindle 1/2/DX, Netronix EB600, Ectaco Jetbook, BeBook/BeBook Mini, Irex Illiad/DR1000, Adroid phones and the iPhone. In addition, using the :guilabel:`Save to disk` function you can use it with any ebook reader that exports itself as a USB disk.
|
||||||
|
|
||||||
I used |app| to transfer some books to my reader, and now the SONY software hangs every time I connect the reader?
|
I used |app| to transfer some books to my reader, and now the SONY software hangs every time I connect the reader?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -180,7 +180,7 @@ else:
|
|||||||
data = dict(version = version, name='osx',
|
data = dict(version = version, name='osx',
|
||||||
installer_name='OS X universal dmg',
|
installer_name='OS X universal dmg',
|
||||||
title='Download %s for OS X'%(__appname__),
|
title='Download %s for OS X'%(__appname__),
|
||||||
compatibility='%s works on OS X Tiger and Leopard, but not Snow Leopard.'%(__appname__,),
|
compatibility='%s works on OS X Tiger and Leopard, but not Snow Leopard (It might work on Snow Leopard if run with Rosetta).'%(__appname__,),
|
||||||
path=MOBILEREAD+file, app=__appname__,
|
path=MOBILEREAD+file, app=__appname__,
|
||||||
note=Markup(\
|
note=Markup(\
|
||||||
u'''
|
u'''
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -4,9 +4,9 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre 0.6.10\n"
|
"Project-Id-Version: calibre 0.6.11\n"
|
||||||
"POT-Creation-Date: 2009-09-01 21:13+MDT\n"
|
"POT-Creation-Date: 2009-09-04 15:35+MDT\n"
|
||||||
"PO-Revision-Date: 2009-09-01 21:13+MDT\n"
|
"PO-Revision-Date: 2009-09-04 15:35+MDT\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: LANGUAGE\n"
|
"Language-Team: LANGUAGE\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -75,8 +75,8 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:33
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:33
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/palmdoc/writer.py:29
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/palmdoc/writer.py:29
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ztxt/writer.py:27
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ztxt/writer.py:27
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:81
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:82
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:82
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:83
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:75
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:75
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:76
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:76
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:61
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:61
|
||||||
@ -127,8 +127,8 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1423
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1423
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1425
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1425
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1534
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1534
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:373
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:419
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:446
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:517
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
||||||
@ -392,8 +392,8 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/devices/cybookg3/driver.py:76
|
#: /home/kovid/work/calibre/src/calibre/devices/cybookg3/driver.py:76
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:76
|
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:76
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:78
|
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:78
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:129
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:130
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:131
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:132
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:99
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:99
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:101
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:101
|
||||||
msgid "Transferring books to device..."
|
msgid "Transferring books to device..."
|
||||||
@ -441,10 +441,10 @@ msgid "Communicate with the Sony PRS-500 eBook reader."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:150
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:150
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:92
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:93
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:95
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:96
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:98
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:99
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:109
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:110
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:49
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:49
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:52
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:52
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:55
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:55
|
||||||
@ -463,14 +463,14 @@ msgstr ""
|
|||||||
msgid "Kovid Goyal and John Schember"
|
msgid "Kovid Goyal and John Schember"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:162
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:163
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:169
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:170
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:119
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:119
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:134
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:134
|
||||||
msgid "Removing books from device..."
|
msgid "Removing books from device..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:197
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:198
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:149
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:149
|
||||||
msgid "Sending metadata to device..."
|
msgid "Sending metadata to device..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -920,7 +920,7 @@ msgstr ""
|
|||||||
msgid "Running transforms on ebook..."
|
msgid "Running transforms on ebook..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:822
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:821
|
||||||
msgid "Creating"
|
msgid "Creating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -940,10 +940,10 @@ msgstr ""
|
|||||||
msgid "Normally, if the input file has no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover."
|
msgid "Normally, if the input file has no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:123
|
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:122
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pml/pmlml.py:111
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pml/pmlml.py:111
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/rb/rbml.py:98
|
#: /home/kovid/work/calibre/src/calibre/ebooks/rb/rbml.py:98
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/txtml.py:70
|
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/txtml.py:72
|
||||||
msgid "Table of Contents:"
|
msgid "Table of Contents:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1623,14 +1623,14 @@ msgid ""
|
|||||||
"Manipulate a PDF.\n"
|
"Manipulate a PDF.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:28
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:29
|
||||||
msgid ""
|
msgid ""
|
||||||
"[options] file.pdf\n"
|
"[options] file.pdf\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Crop a PDF file.\n"
|
"Crop a PDF file.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:37
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:38
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:34
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:34
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:32
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:32
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:36
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:36
|
||||||
@ -1640,31 +1640,31 @@ msgstr ""
|
|||||||
msgid "Path to output file. By default a file is created in the current directory."
|
msgid "Path to output file. By default a file is created in the current directory."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:40
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:41
|
||||||
msgid "Number of pixels to crop from the left most x (default is %s)"
|
msgid "Number of pixels to crop from the left most x (default is %s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:43
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:44
|
||||||
msgid "Number of pixels to crop from the left most y (default is %s)"
|
msgid "Number of pixels to crop from the left most y (default is %s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:46
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:47
|
||||||
msgid "Number of pixels to crop from the right most x (default is %s)"
|
msgid "Number of pixels to crop from the right most x (default is %s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:49
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:50
|
||||||
msgid "Number of pixels to crop from the right most y (default is %s)"
|
msgid "Number of pixels to crop from the right most y (default is %s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:52
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:53
|
||||||
msgid "A file generated by ghostscript which allows each page to be individually cropped `gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=bbox file.pdf 2> bounding`"
|
msgid "A file generated by ghostscript which allows each page to be individually cropped `gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=bbox file.pdf 2> bounding`"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:72
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:73
|
||||||
msgid "Crop Options:"
|
msgid "Crop Options:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:72
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:73
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:62
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:62
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:52
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:52
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:56
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:56
|
||||||
@ -1810,7 +1810,7 @@ msgid "This RTF file has a feature calibre does not support. Convert it to HTML
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:26
|
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:26
|
||||||
msgid "Run the text input though the markdown processor."
|
msgid "Run the text input through the markdown pre-processor. To learn more about markdown see"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:24
|
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:24
|
||||||
@ -1821,6 +1821,15 @@ msgstr ""
|
|||||||
msgid "Specify the character encoding of the output document. The default is utf-8. Note: This option is not honored by all formats."
|
msgid "Specify the character encoding of the output document. The default is utf-8. Note: This option is not honored by all formats."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:38
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:44
|
||||||
|
msgid "Do not add a blank line between paragraphs."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:41
|
||||||
|
msgid "Add a tab at the beginning of each paragraph."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:28
|
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:28
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:505
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:505
|
||||||
msgid "Frequently used directories"
|
msgid "Frequently used directories"
|
||||||
@ -2021,8 +2030,8 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:28
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:28
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:67
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:67
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:61
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:61
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:28
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:35
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:35
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:41
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_edit_ui.py:41
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_edit_ui.py:41
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:67
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:67
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:59
|
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:59
|
||||||
@ -2124,7 +2133,7 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:509
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:509
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:525
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:525
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:526
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:526
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:557
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:556
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:343
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:343
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:348
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:348
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:362
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:362
|
||||||
@ -2192,7 +2201,7 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:29
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:29
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:37
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:37
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:29
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:29
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:37
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:43
|
||||||
msgid "&Inline TOC"
|
msgid "&Inline TOC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2498,7 +2507,7 @@ msgid "PDB Input"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:29
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:29
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:29
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:36
|
||||||
msgid "Treat each &line as a paragraph"
|
msgid "Treat each &line as a paragraph"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2686,14 +2695,26 @@ msgstr ""
|
|||||||
msgid "TXT Input"
|
msgid "TXT Input"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:37
|
||||||
|
msgid "Process using markdown"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:38
|
||||||
|
msgid "<p>Markdown is a simple markup language for text files, that allows for advanced formatting. To learn more visit <a href=\"http://daringfireball.net/projects/markdown\">markdown</a>."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:16
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:16
|
||||||
msgid "TXT Output"
|
msgid "TXT Output"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:36
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:42
|
||||||
msgid "&Line ending style:"
|
msgid "&Line ending style:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:45
|
||||||
|
msgid "Add a tab at the beginning of each paragraph"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_edit_ui.py:42
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_edit_ui.py:42
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:62
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:62
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:63
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:63
|
||||||
@ -3099,117 +3120,126 @@ msgstr ""
|
|||||||
msgid "new email address"
|
msgid "new email address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:467
|
|
||||||
msgid "Command line tools installed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:468
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:468
|
||||||
msgid "Command line tools installed in"
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:801
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:518
|
|
||||||
msgid "No valid plugin path"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:519
|
|
||||||
msgid "%s is not a valid plugin path"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:522
|
|
||||||
msgid "Choose plugin"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:534
|
|
||||||
msgid "Plugin cannot be disabled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:535
|
|
||||||
msgid "The plugin: %s cannot be disabled"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:544
|
|
||||||
msgid "Plugin not customizable"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:545
|
|
||||||
msgid "Plugin: %s does not need customization"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:569
|
|
||||||
msgid "Customize %s"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:579
|
|
||||||
msgid "Cannot remove builtin plugin"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:580
|
|
||||||
msgid " cannot be removed. It is a builtin plugin. Try disabling it instead."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:613
|
|
||||||
msgid "Error log:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:620
|
|
||||||
msgid "Access log:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:645
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:574
|
|
||||||
msgid "Failed to start content server"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:669
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:471
|
|
||||||
msgid "Select location for books"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:686
|
|
||||||
msgid "Invalid size"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:687
|
|
||||||
msgid "The size %s is invalid. must be of the form widthxheight"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:731
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:736
|
|
||||||
msgid "Invalid database location"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:732
|
|
||||||
msgid "Invalid database location "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:733
|
|
||||||
msgid "<br>Must be a directory."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:737
|
|
||||||
msgid "Invalid database location.<br>Cannot write to "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:775
|
|
||||||
msgid "Checking database integrity"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:794
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:142
|
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:142
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005
|
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:52
|
#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:52
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:795
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:469
|
||||||
|
msgid "Failed to install command line tools."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:472
|
||||||
|
msgid "Command line tools installed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:473
|
||||||
|
msgid "Command line tools installed in"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:474
|
||||||
|
msgid "If you move calibre.app, you have to re-install the command line tools."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:525
|
||||||
|
msgid "No valid plugin path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:526
|
||||||
|
msgid "%s is not a valid plugin path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:529
|
||||||
|
msgid "Choose plugin"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:541
|
||||||
|
msgid "Plugin cannot be disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:542
|
||||||
|
msgid "The plugin: %s cannot be disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:551
|
||||||
|
msgid "Plugin not customizable"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:552
|
||||||
|
msgid "Plugin: %s does not need customization"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:576
|
||||||
|
msgid "Customize %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:586
|
||||||
|
msgid "Cannot remove builtin plugin"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:587
|
||||||
|
msgid " cannot be removed. It is a builtin plugin. Try disabling it instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:620
|
||||||
|
msgid "Error log:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:627
|
||||||
|
msgid "Access log:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:652
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/main.py:574
|
||||||
|
msgid "Failed to start content server"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:676
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:471
|
||||||
|
msgid "Select location for books"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:693
|
||||||
|
msgid "Invalid size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:694
|
||||||
|
msgid "The size %s is invalid. must be of the form widthxheight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:738
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:743
|
||||||
|
msgid "Invalid database location"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:739
|
||||||
|
msgid "Invalid database location "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:740
|
||||||
|
msgid "<br>Must be a directory."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:744
|
||||||
|
msgid "Invalid database location.<br>Cannot write to "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:782
|
||||||
|
msgid "Checking database integrity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:802
|
||||||
msgid "Failed to check database integrity"
|
msgid "Failed to check database integrity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:800
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:807
|
||||||
msgid "Some inconsistencies found"
|
msgid "Some inconsistencies found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:801
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:808
|
||||||
msgid "The following books had formats listed in the database that are not actually available. The entries for the formats have been removed. You should check them manually. This can happen if you manipulate the files in the library folder directly."
|
msgid "The following books had formats listed in the database that are not actually available. The entries for the formats have been removed. You should check them manually. This can happen if you manipulate the files in the library folder directly."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3444,109 +3474,105 @@ msgid "calibre can send your books to you (or your reader) by email"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:533
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:533
|
||||||
msgid "Free unused diskspace from the database"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:534
|
|
||||||
msgid "&Check database integrity"
|
msgid "&Check database integrity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:535
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:534
|
||||||
msgid "&Install command line tools"
|
msgid "&Install command line tools"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:536
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:535
|
||||||
msgid "calibre contains a network server that allows you to access your book collection using a browser from anywhere in the world. Any changes to the settings will only take effect after a server restart."
|
msgid "calibre contains a network server that allows you to access your book collection using a browser from anywhere in the world. Any changes to the settings will only take effect after a server restart."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:537
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:536
|
||||||
msgid "Server &port:"
|
msgid "Server &port:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:538
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:537
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:58
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:58
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:178
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:178
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:117
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:117
|
||||||
msgid "&Username:"
|
msgid "&Username:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:539
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:538
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:59
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:59
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:179
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:179
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:119
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:119
|
||||||
msgid "&Password:"
|
msgid "&Password:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:540
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:539
|
||||||
msgid "If you leave the password blank, anyone will be able to access your book collection using the web interface."
|
msgid "If you leave the password blank, anyone will be able to access your book collection using the web interface."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:541
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:540
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:60
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:60
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:180
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:180
|
||||||
msgid "&Show password"
|
msgid "&Show password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:542
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:541
|
||||||
msgid "The maximum size (widthxheight) for displayed covers. Larger covers are resized. "
|
msgid "The maximum size (widthxheight) for displayed covers. Larger covers are resized. "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:543
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:542
|
||||||
msgid "Max. &cover size:"
|
msgid "Max. &cover size:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:544
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:543
|
||||||
msgid "&Start Server"
|
msgid "&Start Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:545
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:544
|
||||||
msgid "St&op Server"
|
msgid "St&op Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:546
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:545
|
||||||
msgid "&Test Server"
|
msgid "&Test Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:547
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:546
|
||||||
msgid "Run server &automatically on startup"
|
msgid "Run server &automatically on startup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:548
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:547
|
||||||
msgid "View &server logs"
|
msgid "View &server logs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:549
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:548
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/stanza_ui.py:46
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/stanza_ui.py:46
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>Remember to leave calibre running as the server only runs as long as calibre is running.\n"
|
"<p>Remember to leave calibre running as the server only runs as long as calibre is running.\n"
|
||||||
"<p>Stanza should see your calibre collection automatically. If not, try adding the URL http://myhostname:8080 as a new catalog in the Stanza reader on your iPhone. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on."
|
"<p>Stanza should see your calibre collection automatically. If not, try adding the URL http://myhostname:8080 as a new catalog in the Stanza reader on your iPhone. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:551
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:550
|
||||||
msgid "Here you can customize the behavior of Calibre by controlling what plugins it uses."
|
msgid "Here you can customize the behavior of Calibre by controlling what plugins it uses."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:552
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:551
|
||||||
msgid "Enable/&Disable plugin"
|
msgid "Enable/&Disable plugin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:553
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:552
|
||||||
msgid "&Customize plugin"
|
msgid "&Customize plugin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:554
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:553
|
||||||
msgid "&Remove plugin"
|
msgid "&Remove plugin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:555
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:554
|
||||||
msgid "Add new plugin"
|
msgid "Add new plugin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:556
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:555
|
||||||
msgid "Plugin &file:"
|
msgid "Plugin &file:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:558
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:557
|
||||||
msgid "&Add"
|
msgid "&Add"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5135,33 +5161,41 @@ msgid "Publishers"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:30
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:30
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:94
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:97
|
||||||
msgid "Starting conversion of %d books"
|
msgid "Starting conversion of %d books"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:53
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:56
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:133
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:137
|
||||||
msgid "Convert book %d of %d (%s)"
|
msgid "Convert book %d of %d (%s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:79
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:82
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:150
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:154
|
||||||
msgid "Could not convert some books"
|
msgid "Could not convert some books"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:80
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:83
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:151
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:155
|
||||||
msgid "Could not convert %d of %d books, because no suitable source format was found."
|
msgid "Could not convert %d of %d books, because no suitable source format was found."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:182
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:186
|
||||||
msgid "You must set a username and password for %s"
|
msgid "You must set a username and password for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:187
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:191
|
||||||
msgid "Fetch news from "
|
msgid "Fetch news from "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:201
|
||||||
|
msgid "Convert existing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:202
|
||||||
|
msgid "The following books have already been converted to %s format. Do you wish to reconvert them?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/bookmarkmanager.py:43
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/bookmarkmanager.py:43
|
||||||
msgid "Edit bookmark"
|
msgid "Edit bookmark"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -6126,11 +6160,11 @@ msgstr ""
|
|||||||
msgid "Requested formats not available"
|
msgid "Requested formats not available"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:203
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:233
|
||||||
msgid "Password to access your calibre library. Username is "
|
msgid "Password to access your calibre library. Username is "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:526
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:598
|
||||||
msgid ""
|
msgid ""
|
||||||
"[options]\n"
|
"[options]\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -6308,19 +6342,19 @@ msgstr ""
|
|||||||
msgid "Downloading cover from %s"
|
msgid "Downloading cover from %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:930
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:932
|
||||||
msgid "Untitled Article"
|
msgid "Untitled Article"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1001
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1003
|
||||||
msgid "Article downloaded: %s"
|
msgid "Article downloaded: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1012
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1014
|
||||||
msgid "Article download failed: %s"
|
msgid "Article download failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1027
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1029
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_borba.py:80
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_borba.py:80
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_glas_srpske.py:76
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_glas_srpske.py:76
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_instapaper.py:59
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_instapaper.py:59
|
||||||
@ -6509,10 +6543,10 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_stackoverflow.py:18
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_stackoverflow.py:18
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_starbulletin.py:19
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_starbulletin.py:19
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_straitstimes.py:22
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_straitstimes.py:22
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_telegraph_uk.py:18
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_telegraph_uk.py:17
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_teleread.py:17
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_teleread.py:17
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_age.py:19
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_age.py:19
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_budget_fashionista.py:25
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_budget_fashionista.py:23
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_nation.py:17
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_nation.py:17
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_oz.py:16
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_oz.py:16
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_register.py:6
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_the_register.py:6
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -63,6 +63,8 @@ def shorten_components_to(length, components):
|
|||||||
if not r:
|
if not r:
|
||||||
r = x.strip()[0] if x.strip() else 'x'
|
r = x.strip()[0] if x.strip() else 'x'
|
||||||
ans.append(r)
|
ans.append(r)
|
||||||
|
if len(os.sep.join(ans)) > length:
|
||||||
|
return shorten_components_to(length, ans)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def find_executable_in_path(name, path=None):
|
def find_executable_in_path(name, path=None):
|
||||||
|
@ -16,6 +16,8 @@ if iswindows:
|
|||||||
import win32process
|
import win32process
|
||||||
_windows_null_file = open(os.devnull, 'wb')
|
_windows_null_file = open(os.devnull, 'wb')
|
||||||
|
|
||||||
|
isnewosx = isosx and getattr(sys, 'new_app_bundle', False)
|
||||||
|
|
||||||
class Worker(object):
|
class Worker(object):
|
||||||
'''
|
'''
|
||||||
Platform independent object for launching child processes. All processes
|
Platform independent object for launching child processes. All processes
|
||||||
@ -45,6 +47,9 @@ class Worker(object):
|
|||||||
return os.path.join(os.path.dirname(sys.executable),
|
return os.path.join(os.path.dirname(sys.executable),
|
||||||
'calibre-parallel.exe' if isfrozen else \
|
'calibre-parallel.exe' if isfrozen else \
|
||||||
'Scripts\\calibre-parallel.exe')
|
'Scripts\\calibre-parallel.exe')
|
||||||
|
if isnewosx:
|
||||||
|
return os.path.join(sys.console_binaries_path, 'calibre-parallel')
|
||||||
|
|
||||||
if isosx:
|
if isosx:
|
||||||
if not isfrozen: return 'calibre-parallel'
|
if not isfrozen: return 'calibre-parallel'
|
||||||
contents = os.path.join(self.osx_contents_dir,
|
contents = os.path.join(self.osx_contents_dir,
|
||||||
@ -56,6 +61,9 @@ class Worker(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def gui_executable(self):
|
def gui_executable(self):
|
||||||
|
if isnewosx:
|
||||||
|
return os.path.join(sys.binaries_path, 'calibre-parallel')
|
||||||
|
|
||||||
if isfrozen and isosx:
|
if isfrozen and isosx:
|
||||||
return os.path.join(self.osx_contents_dir,
|
return os.path.join(self.osx_contents_dir,
|
||||||
'MacOS', self.osx_interpreter)
|
'MacOS', self.osx_interpreter)
|
||||||
@ -98,7 +106,7 @@ class Worker(object):
|
|||||||
def __init__(self, env, gui=False):
|
def __init__(self, env, gui=False):
|
||||||
self._env = {}
|
self._env = {}
|
||||||
self.gui = gui
|
self.gui = gui
|
||||||
if isosx and isfrozen:
|
if isosx and isfrozen and not isnewosx:
|
||||||
contents = os.path.join(self.osx_contents_dir, 'console.app', 'Contents')
|
contents = os.path.join(self.osx_contents_dir, 'console.app', 'Contents')
|
||||||
resources = os.path.join(contents, 'Resources')
|
resources = os.path.join(contents, 'Resources')
|
||||||
fd = os.path.join(contents, 'Frameworks')
|
fd = os.path.join(contents, 'Frameworks')
|
||||||
@ -133,7 +141,7 @@ class Worker(object):
|
|||||||
if priority is None:
|
if priority is None:
|
||||||
priority = prefs['worker_process_priority']
|
priority = prefs['worker_process_priority']
|
||||||
cmd = [exe]
|
cmd = [exe]
|
||||||
if isosx:
|
if isosx and not isnewosx:
|
||||||
cmd += ['-c', self.osx_prefix + 'from calibre.utils.ipc.worker import main; main()']
|
cmd += ['-c', self.osx_prefix + 'from calibre.utils.ipc.worker import main; main()']
|
||||||
args = {
|
args = {
|
||||||
'env' : env,
|
'env' : env,
|
||||||
@ -155,7 +163,7 @@ class Worker(object):
|
|||||||
ret = self._file.name
|
ret = self._file.name
|
||||||
|
|
||||||
if iswindows and 'stdin' not in args:
|
if iswindows and 'stdin' not in args:
|
||||||
# On windows when usingthepythonw interpreter,
|
# On windows when using the pythonw interpreter,
|
||||||
# stdout, stderr and stdin may not be valid
|
# stdout, stderr and stdin may not be valid
|
||||||
args['stdin'] = subprocess.PIPE
|
args['stdin'] = subprocess.PIPE
|
||||||
args['stdout'] = _windows_null_file
|
args['stdout'] = _windows_null_file
|
||||||
|
@ -6,14 +6,18 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
AUTHTOOL="""#!%s
|
import sys, os
|
||||||
|
|
||||||
|
AUTHTOOL="""#!/usr/bin/python
|
||||||
import os
|
import os
|
||||||
scripts = %s
|
scripts = %s
|
||||||
links = %s
|
links = %s
|
||||||
os.setuid(0)
|
os.setuid(0)
|
||||||
for s, l in zip(scripts, links):
|
for s, l in zip(scripts, links):
|
||||||
if os.path.lexists(l):
|
try:
|
||||||
os.remove(l)
|
os.remove(l)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
print 'Creating link:', l, '->', s
|
print 'Creating link:', l, '->', s
|
||||||
omask = os.umask(022)
|
omask = os.umask(022)
|
||||||
os.symlink(s, l)
|
os.symlink(s, l)
|
||||||
@ -23,15 +27,31 @@ for s, l in zip(scripts, links):
|
|||||||
DEST_PATH = '/usr/bin'
|
DEST_PATH = '/usr/bin'
|
||||||
|
|
||||||
def create_symlinks():
|
def create_symlinks():
|
||||||
import os, tempfile, traceback, sys
|
return create_symlinks_new() if getattr(sys, 'new_app_bundle', False) else create_symlinks_old()
|
||||||
from Authorization import Authorization, kAuthorizationFlagDestroyRights
|
|
||||||
|
def create_symlinks_new():
|
||||||
from calibre.resources import scripts
|
from calibre.resources import scripts
|
||||||
|
|
||||||
|
links = [os.path.join(DEST_PATH, i) for i in scripts]
|
||||||
|
scripts = [os.path.join(
|
||||||
|
sys.binaries_path if scripts[i] == 'gui' else sys.console_binaries_path, i) for i in scripts]
|
||||||
|
|
||||||
|
return do_it(scripts, links)
|
||||||
|
|
||||||
|
|
||||||
|
def create_symlinks_old():
|
||||||
|
from calibre.resources import scripts
|
||||||
|
|
||||||
resources_path = os.environ['RESOURCEPATH']
|
resources_path = os.environ['RESOURCEPATH']
|
||||||
links = [os.path.join(DEST_PATH, i) for i in scripts]
|
links = [os.path.join(DEST_PATH, i) for i in scripts]
|
||||||
scripts = [os.path.join(resources_path, 'loaders', i) for i in scripts]
|
scripts = [os.path.join(resources_path, 'loaders', i) for i in scripts]
|
||||||
|
|
||||||
|
return do_it(scripts, links)
|
||||||
|
|
||||||
|
def do_it(scripts, links):
|
||||||
|
import os, tempfile, traceback
|
||||||
|
from Authorization import Authorization, kAuthorizationFlagDestroyRights
|
||||||
|
r1, r2 = DEST_PATH, links
|
||||||
bad = False
|
bad = False
|
||||||
for s, l in zip(scripts, links):
|
for s, l in zip(scripts, links):
|
||||||
if os.path.exists(l) and os.path.exists(os.path.realpath(l)):
|
if os.path.exists(l) and os.path.exists(os.path.realpath(l)):
|
||||||
@ -39,19 +59,28 @@ def create_symlinks():
|
|||||||
bad = True
|
bad = True
|
||||||
break
|
break
|
||||||
if bad:
|
if bad:
|
||||||
|
ph, pp = os.environ.get('PYTHONHOME', None), os.environ.get('PYTHONPATH', None)
|
||||||
auth = Authorization(destroyflags=(kAuthorizationFlagDestroyRights,))
|
auth = Authorization(destroyflags=(kAuthorizationFlagDestroyRights,))
|
||||||
fd, name = tempfile.mkstemp('.py')
|
fd, name = tempfile.mkstemp('.py')
|
||||||
os.write(fd, AUTHTOOL % (sys.executable, repr(scripts), repr(links)))
|
os.write(fd, AUTHTOOL % (repr(scripts), repr(links)))
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
os.chmod(name, 0700)
|
os.chmod(name, 0700)
|
||||||
try:
|
try:
|
||||||
pipe = auth.executeWithPrivileges(sys.executable, name)
|
if pp:
|
||||||
|
del os.environ['PYTHONPATH']
|
||||||
|
if ph:
|
||||||
|
del os.environ['PYTHONHOME']
|
||||||
|
pipe = auth.executeWithPrivileges(name)
|
||||||
sys.stdout.write(pipe.read())
|
sys.stdout.write(pipe.read())
|
||||||
pipe.close()
|
pipe.close()
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
r1, r2 = None, traceback.format_exc()
|
||||||
finally:
|
finally:
|
||||||
os.unlink(name)
|
os.unlink(name)
|
||||||
|
if pp:
|
||||||
|
os.environ['PYTHONPATH'] = pp
|
||||||
|
if ph:
|
||||||
|
os.environ['PYTHONHOME'] = ph
|
||||||
|
|
||||||
return DEST_PATH, links
|
return r1, r2
|
||||||
|
|
||||||
|
@ -61,7 +61,9 @@ class Economist(BasicNewsRecipe):
|
|||||||
continue
|
continue
|
||||||
a = tag.find('a', href=True)
|
a = tag.find('a', href=True)
|
||||||
if a is not None:
|
if a is not None:
|
||||||
url=a['href'].replace('displaystory', 'PrinterFriendly')
|
url=a['href'].replace('displaystory', 'PrinterFriendly').strip()
|
||||||
|
if url.startswith('Printer'):
|
||||||
|
url = '/'+url
|
||||||
if url.startswith('/'):
|
if url.startswith('/'):
|
||||||
url = 'http://www.economist.com' + url
|
url = 'http://www.economist.com' + url
|
||||||
try:
|
try:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
__copyright__ = '2008-2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
'''
|
'''
|
||||||
latimes.com
|
latimes.com
|
||||||
'''
|
'''
|
||||||
@ -10,20 +10,56 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
|||||||
|
|
||||||
class LATimes(BasicNewsRecipe):
|
class LATimes(BasicNewsRecipe):
|
||||||
title = u'The Los Angeles Times'
|
title = u'The Los Angeles Times'
|
||||||
__author__ = u'Darko Miletic'
|
__author__ = u'Darko Miletic and Sujata Raman'
|
||||||
description = u'News from Los Angeles'
|
description = u'News from Los Angeles'
|
||||||
oldest_article = 7
|
oldest_article = 7
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
language = _('English')
|
language = _('English')
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
use_embedded_content = False
|
use_embedded_content = False
|
||||||
|
encoding = 'utf-8'
|
||||||
|
lang = 'en-US'
|
||||||
|
|
||||||
keep_only_tags = [ dict(name='div', attrs={'id':'center' }) ]
|
conversion_options = {
|
||||||
remove_tags_after = [ dict(name='div', attrs={'id':'socialnet'}) ]
|
'comment' : description
|
||||||
remove_tags = [
|
, 'language' : lang
|
||||||
dict(name='div' , attrs={'id':'wrapper_vid' })
|
}
|
||||||
,dict(name='div' , attrs={'id':'article_related'})
|
|
||||||
,dict(name='div' , attrs={'id':'socialnet' })
|
extra_css = '''
|
||||||
|
h1{font-family :Georgia,"Times New Roman",Times,serif; font-size:large; }
|
||||||
|
h2{font-family :Georgia,"Times New Roman",Times,serif; font-size:x-small;}
|
||||||
|
.story{font-family :Georgia,"Times New Roman",Times,serif; font-size: x-small;}
|
||||||
|
.entry-body{font-family :Georgia,"Times New Roman",Times,serif; font-size: x-small;}
|
||||||
|
.entry-more{font-family :Georgia,"Times New Roman",Times,serif; font-size: x-small;}
|
||||||
|
.credit{color:#666666; font-family :Georgia,"Times New Roman",Times,serif; font-size: xx-small;}
|
||||||
|
.small{color:#666666; font-family :Georgia,"Times New Roman",Times,serif; font-size: xx-small;}
|
||||||
|
.byline{font-family :Georgia,"Times New Roman",Times,serif; font-size: xx-small;}
|
||||||
|
.date{font-family :Georgia,"Times New Roman",Times,serif; font-size: xx-small;color:#930000; font-style:italic;}
|
||||||
|
.time{font-family :Georgia,"Times New Roman",Times,serif; font-size: xx-small;color:#930000; font-style:italic;}
|
||||||
|
.copyright{font-family :Georgia,"Times New Roman",Times,serif; font-size: xx-small;color:#930000; }
|
||||||
|
.subhead{font-family :Georgia,"Times New Roman",Times,serif; font-size:x-small;}
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'class':["story" ,"entry"] })]
|
||||||
|
remove_tags = [ dict(name='div', attrs={'class':['articlerail',"sphereTools","tools","toppaginate","entry-footer-left","entry-footer-right"]}),
|
||||||
|
dict(name='div', attrs={'id':["moduleArticleToolsContainer",]}),
|
||||||
|
dict(name='ul', attrs={'class':["article-nav clearfix",]}),
|
||||||
|
dict(name='p', attrs={'class':["entry-footer",]}),
|
||||||
|
dict(name=['iframe'])
|
||||||
]
|
]
|
||||||
|
|
||||||
feeds = [(u'News', u'http://feeds.latimes.com/latimes/news')]
|
feeds = [(u'News', u'http://feeds.latimes.com/latimes/news')
|
||||||
|
,(u'Local','http://feeds.latimes.com/latimes/news/local')
|
||||||
|
,(u'Most Emailed','http://feeds.latimes.com/MostEmailed')
|
||||||
|
,(u'California Politics','http://feeds.latimes.com/latimes/news/local/politics/cal/')
|
||||||
|
,('OrangeCounty','http://feeds.latimes.com/latimes/news/local/orange/')
|
||||||
|
,('National','http://feeds.latimes.com/latimes/news/nationworld/nation')
|
||||||
|
,('Politics','http://feeds.latimes.com/latimes/news/politics/')
|
||||||
|
,('Business','http://feeds.latimes.com/latimes/business')
|
||||||
|
,('Sports','http://feeds.latimes.com/latimes/sports/')
|
||||||
|
,('Entertainment','http://feeds.latimes.com/latimes/entertainment/')
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
return article.get('feedburner_origlink')
|
||||||
|
@ -89,6 +89,17 @@ class Newsweek(BasicNewsRecipe):
|
|||||||
return cmp(tx, ty)
|
return cmp(tx, ty)
|
||||||
return sorted(ans, cmp=fcmp)
|
return sorted(ans, cmp=fcmp)
|
||||||
|
|
||||||
|
def ensure_html(self, soup):
|
||||||
|
root = soup.find(name=True)
|
||||||
|
if root.name == 'html': return soup
|
||||||
|
nsoup = BeautifulSoup('<html><head></head><body/></html>')
|
||||||
|
nroot = nsoup.find(name='body')
|
||||||
|
for x in soup.contents:
|
||||||
|
if getattr(x, 'name', False):
|
||||||
|
x.extract()
|
||||||
|
nroot.insert(len(nroot), x)
|
||||||
|
return nsoup
|
||||||
|
|
||||||
def postprocess_html(self, soup, first_fetch):
|
def postprocess_html(self, soup, first_fetch):
|
||||||
if not first_fetch:
|
if not first_fetch:
|
||||||
h1 = soup.find(id='headline')
|
h1 = soup.find(id='headline')
|
||||||
@ -99,7 +110,7 @@ class Newsweek(BasicNewsRecipe):
|
|||||||
div.extract()
|
div.extract()
|
||||||
divs = list(soup.findAll('div', 'pagination'))
|
divs = list(soup.findAll('div', 'pagination'))
|
||||||
if not divs:
|
if not divs:
|
||||||
return soup
|
return self.ensure_html(soup)
|
||||||
for div in divs[1:]: div.extract()
|
for div in divs[1:]: div.extract()
|
||||||
all_a = divs[0].findAll('a', href=True)
|
all_a = divs[0].findAll('a', href=True)
|
||||||
divs[0]['style']="display:none"
|
divs[0]['style']="display:none"
|
||||||
@ -109,7 +120,7 @@ class Newsweek(BasicNewsRecipe):
|
|||||||
for a in soup.findAll('a', href=test):
|
for a in soup.findAll('a', href=test):
|
||||||
if a not in all_a:
|
if a not in all_a:
|
||||||
del a['href']
|
del a['href']
|
||||||
return soup
|
return self.ensure_html(soup)
|
||||||
|
|
||||||
def get_current_issue(self):
|
def get_current_issue(self):
|
||||||
soup = self.index_to_soup('http://www.newsweek.com')
|
soup = self.index_to_soup('http://www.newsweek.com')
|
||||||
@ -132,7 +143,7 @@ class Newsweek(BasicNewsRecipe):
|
|||||||
def postprocess_book(self, oeb, opts, log) :
|
def postprocess_book(self, oeb, opts, log) :
|
||||||
|
|
||||||
def extractByline(href) :
|
def extractByline(href) :
|
||||||
soup = BeautifulSoup(str(oeb.manifest.hrefs[href]))
|
soup = BeautifulSoup(str(oeb.manifest.hrefs[href]))
|
||||||
byline = soup.find(True,attrs={'class':'authorInfo'})
|
byline = soup.find(True,attrs={'class':'authorInfo'})
|
||||||
byline = self.tag_to_string(byline) if byline is not None else ''
|
byline = self.tag_to_string(byline) if byline is not None else ''
|
||||||
issueDate = soup.find(True,attrs={'class':'issueDate'})
|
issueDate = soup.find(True,attrs={'class':'issueDate'})
|
||||||
@ -142,7 +153,7 @@ class Newsweek(BasicNewsRecipe):
|
|||||||
return byline + ' | ' + issueDate
|
return byline + ' | ' + issueDate
|
||||||
else :
|
else :
|
||||||
return byline + issueDate
|
return byline + issueDate
|
||||||
|
|
||||||
def extractDescription(href) :
|
def extractDescription(href) :
|
||||||
soup = BeautifulSoup(str(oeb.manifest.hrefs[href]))
|
soup = BeautifulSoup(str(oeb.manifest.hrefs[href]))
|
||||||
description = soup.find(True,attrs={'name':'description'})
|
description = soup.find(True,attrs={'name':'description'})
|
||||||
@ -156,8 +167,8 @@ class Newsweek(BasicNewsRecipe):
|
|||||||
description = soup.find(True, attrs={'class':'story'})
|
description = soup.find(True, attrs={'class':'story'})
|
||||||
firstPara = soup.find('p')
|
firstPara = soup.find('p')
|
||||||
description = self.tag_to_string(firstPara)
|
description = self.tag_to_string(firstPara)
|
||||||
return description
|
return description
|
||||||
|
|
||||||
for section in oeb.toc :
|
for section in oeb.toc :
|
||||||
for article in section :
|
for article in section :
|
||||||
if article.author is None :
|
if article.author is None :
|
||||||
|
@ -1,38 +1,58 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
__license__ = 'GPL v3'
|
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
'''
|
||||||
'''
|
telegraph.co.uk
|
||||||
telegraph.co.uk
|
'''
|
||||||
'''
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
|
||||||
|
class TelegraphUK(BasicNewsRecipe):
|
||||||
class TelegraphUK(BasicNewsRecipe):
|
title = u'Telegraph.co.uk'
|
||||||
title = u'Telegraph.co.uk'
|
__author__ = 'Darko Miletic'
|
||||||
__author__ = 'Darko Miletic'
|
description = 'News from United Kingdom'
|
||||||
description = 'News from United Kingdom'
|
oldest_article = 7
|
||||||
oldest_article = 7
|
max_articles_per_feed = 100
|
||||||
max_articles_per_feed = 100
|
no_stylesheets = True
|
||||||
no_stylesheets = True
|
language = _('English')
|
||||||
language = _('English')
|
use_embedded_content = False
|
||||||
use_embedded_content = False
|
|
||||||
|
extra_css = '''
|
||||||
keep_only_tags = [
|
h1{font-family :Arial,Helvetica,sans-serif; font-size:large; }
|
||||||
dict(name='div', attrs={'class':'storyHead'})
|
h2{font-family :Arial,Helvetica,sans-serif; font-size:x-small; color:#444444}
|
||||||
,dict(name='div', attrs={'class':'story' })
|
.story{font-family :Arial,Helvetica,sans-serif; font-size: x-small;}
|
||||||
]
|
.byline{color:#666666; font-family :Arial,Helvetica,sans-serif; font-size: xx-small;}
|
||||||
remove_tags = [dict(name='div', attrs={'class':'slideshow'})]
|
a{color:#234B7B; }
|
||||||
|
.imageExtras{color:#666666; font-family :Arial,Helvetica,sans-serif; font-size: xx-small;}
|
||||||
feeds = [
|
'''
|
||||||
(u'UK News' , u'http://www.telegraph.co.uk/news/uknews/rss' )
|
|
||||||
,(u'World News' , u'http://www.telegraph.co.uk/news/worldnews/rss' )
|
keep_only_tags = [
|
||||||
,(u'Politics' , u'http://www.telegraph.co.uk/news/newstopics/politics/rss' )
|
dict(name='div', attrs={'class':'storyHead'})
|
||||||
,(u'Technology News', u'http://www.telegraph.co.uk/scienceandtechnology/technology/technologynews/rss' )
|
,dict(name='div', attrs={'class':'story' })
|
||||||
,(u'UK News' , u'http://www.telegraph.co.uk/scienceandtechnology/technology/technologyreviews/rss')
|
#,dict(name='div', attrs={'class':['slideshowHD gutterUnder',"twoThirds gutter","caption" ] })
|
||||||
,(u'Science News' , u'http://www.telegraph.co.uk/scienceandtechnology/science/sciencenews/rss' )
|
]
|
||||||
,(u'Sport' , u'http://www.telegraph.co.uk/sport/rss' )
|
remove_tags = [dict(name='div', attrs={'class':['related_links_inline',"imgindex","next","prev","gutterUnder"]})]
|
||||||
,(u'Earth News' , u'http://www.telegraph.co.uk/earth/earthnews/rss' )
|
|
||||||
,(u'Comment' , u'http://www.telegraph.co.uk/comment/rss' )
|
feeds = [
|
||||||
,(u'How about that?', u'http://www.telegraph.co.uk/news/newstopics/howaboutthat/rss' )
|
(u'UK News' , u'http://www.telegraph.co.uk/news/uknews/rss' )
|
||||||
]
|
,(u'World News' , u'http://www.telegraph.co.uk/news/worldnews/rss' )
|
||||||
|
,(u'Politics' , u'http://www.telegraph.co.uk/news/newstopics/politics/rss' )
|
||||||
|
,(u'Technology News', u'http://www.telegraph.co.uk/scienceandtechnology/technology/technologynews/rss' )
|
||||||
|
,(u'UK News' , u'http://www.telegraph.co.uk/scienceandtechnology/technology/technologyreviews/rss')
|
||||||
|
,(u'Science News' , u'http://www.telegraph.co.uk/scienceandtechnology/science/sciencenews/rss' )
|
||||||
|
,(u'Sport' , u'http://www.telegraph.co.uk/sport/rss' )
|
||||||
|
,(u'Earth News' , u'http://www.telegraph.co.uk/earth/earthnews/rss' )
|
||||||
|
,(u'Comment' , u'http://www.telegraph.co.uk/comment/rss' )
|
||||||
|
,(u'How about that?', u'http://www.telegraph.co.uk/news/newstopics/howaboutthat/rss' )
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
|
||||||
|
url = article.get('guid', None)
|
||||||
|
|
||||||
|
if 'picture-galleries' in url or 'pictures' in url or 'picturegalleries' in url :
|
||||||
|
url = None
|
||||||
|
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,9 +6,7 @@ __copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
|||||||
www.thebudgetfashionista.com
|
www.thebudgetfashionista.com
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re
|
|
||||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||||
from calibre.ebooks.BeautifulSoup import Tag
|
|
||||||
|
|
||||||
class TheBudgetFashionista(BasicNewsRecipe):
|
class TheBudgetFashionista(BasicNewsRecipe):
|
||||||
title = 'The Budget Fashionista'
|
title = 'The Budget Fashionista'
|
||||||
@ -24,40 +22,22 @@ class TheBudgetFashionista(BasicNewsRecipe):
|
|||||||
lang = 'en-US'
|
lang = 'en-US'
|
||||||
language = _('English')
|
language = _('English')
|
||||||
|
|
||||||
preprocess_regexps = [(re.compile(r"</head>{0,1}", re.DOTALL|re.IGNORECASE),lambda match: '')]
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : lang
|
||||||
|
}
|
||||||
|
|
||||||
html2lrf_options = [
|
keep_only_tags = [dict(name='div', attrs={'class':'columnLeft'})]
|
||||||
'--comment', description
|
remove_tags_after = dict(name='div', attrs={'class':'postDetails'})
|
||||||
, '--category', category
|
remove_tags = [dict(name=['object','link','script','iframe','form','login-button'])]
|
||||||
, '--publisher', publisher
|
|
||||||
]
|
|
||||||
|
|
||||||
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
|
||||||
|
|
||||||
keep_only_tags = [dict(name='div', attrs={'id':'singlepost'})]
|
|
||||||
remove_tags_after = dict(name='div', attrs={'id':'postnav'})
|
|
||||||
remove_tags = [
|
|
||||||
dict(name=['object','link','script','iframe','form'])
|
|
||||||
,dict(name='div', attrs={'id':'postnav'})
|
|
||||||
]
|
|
||||||
|
|
||||||
feeds = [(u'Articles', u'http://www.thebudgetfashionista.com/feeds/atom/')]
|
feeds = [(u'Articles', u'http://www.thebudgetfashionista.com/feeds/atom/')]
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
for item in soup.findAll(style=True):
|
for it in soup.findAll('img'):
|
||||||
del item['style']
|
if it.parent.name == 'a':
|
||||||
return soup
|
it.parent.name = 'div'
|
||||||
|
return soup;
|
||||||
|
|
||||||
def postprocess_html(self, soup, x):
|
|
||||||
body = soup.find('body')
|
|
||||||
post = soup.find('div', attrs={'id':'singlepost'})
|
|
||||||
if post and body:
|
|
||||||
post.extract()
|
|
||||||
body.extract()
|
|
||||||
soup.html.append(body)
|
|
||||||
body.insert(1,post)
|
|
||||||
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)])
|
|
||||||
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=utf-8")])
|
|
||||||
soup.head.insert(0,mlang)
|
|
||||||
soup.head.insert(1,mcharset)
|
|
||||||
return self.adeify_images(soup)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user