Merge upstream changes

This commit is contained in:
Marshall T. Vandegrift 2009-01-26 08:26:30 -05:00
commit 3b5b9f1849
8 changed files with 86 additions and 28 deletions

View File

@ -3,7 +3,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
''' Create an OSX installer '''
import sys, re, os, shutil, subprocess, stat, glob, zipfile
import sys, re, os, shutil, subprocess, stat, glob, zipfile, plistlib
l = {}
exec open('setup.py').read() in l
VERSION = l['VERSION']
@ -36,7 +36,7 @@ loader = open(loader_path, 'w')
site_packages = glob.glob(resources_dir+'/lib/python*/site-packages.zip')[0]
print >>loader, '#!'+python
print >>loader, 'import sys'
print >>loader, 'sys.path.remove('+repr(dirpath)+')'
print >>loader, 'if', repr(dirpath), 'in sys.path: sys.path.remove(', repr(dirpath), ')'
print >>loader, 'sys.path.append(', repr(site_packages), ')'
print >>loader, 'sys.frozen = "macosx_app"'
print >>loader, 'sys.frameworks_dir =', repr(frameworks_dir)
@ -294,11 +294,26 @@ sys.frameworks_dir = os.path.join(os.path.dirname(os.environ['RESOURCEPATH']), '
f.close()
print
print 'Adding main scripts to site-packages'
f = zipfile.ZipFile(os.path.join(self.dist_dir, APPNAME+'.app', 'Contents', 'Resources', 'lib', 'python2.6', 'site-packages.zip'), 'a', zipfile.ZIP_DEFLATED)
f = zipfile.ZipFile(os.path.join(self.dist_dir, APPNAME+'.app', 'Contents', 'Resources', 'lib', 'python'+sys.version[:3], 'site-packages.zip'), 'a', zipfile.ZIP_DEFLATED)
for script in scripts['gui']+scripts['console']:
f.write(script, script.partition('/')[-1])
f.close()
print
print 'Creating console.app'
contents_dir = os.path.dirname(resource_dir)
cc_dir = os.path.join(contents_dir, 'console.app', 'Contents')
os.makedirs(cc_dir)
for x in os.listdir(contents_dir):
if x == 'console.app':
continue
if x == 'Info.plist':
plist = plistlib.readPlist(os.path.join(contents_dir, x))
plist['LSUIElement'] = '1'
plistlib.writePlist(plist, os.path.join(cc_dir, x))
else:
os.symlink(os.path.join('../..', x),
os.path.join(cc_dir, x))
print
print 'Building disk image'
BuildAPP.makedmg(os.path.join(self.dist_dir, APPNAME+'.app'), APPNAME+'-'+VERSION)

View File

@ -21,6 +21,7 @@ Run an embedded python interpreter.
'Module specifications are of the form full.name.of.module,path_to_module.py', default=None
)
parser.add_option('-c', '--command', help='Run python code.', default=None)
parser.add_option('-e', '--exec-file', default=None, help='Run the python code in file.')
parser.add_option('-g', '--gui', default=False, action='store_true',
help='Run the GUI',)
parser.add_option('--migrate', action='store_true', default=False,
@ -87,6 +88,9 @@ def main(args=sys.argv):
elif opts.command:
sys.argv = args[:1]
exec opts.command
elif opts.exec_file:
sys.argv = args[:1]
execfile(opts.exec_file)
elif opts.migrate:
if len(args) < 3:
print 'You must specify the path to library1.db and the path to the new library folder'

View File

@ -194,6 +194,8 @@ class HTMLProcessor(Processor, Rationalizer):
if not tag.text and not tag.get('src', False):
tag.getparent().remove(tag)
def save(self):
for meta in list(self.root.xpath('//meta')):
meta.getparent().remove(meta)

View File

@ -417,39 +417,44 @@ class Parser(PreProcessor, LoggingInterface):
self.level = self.htmlfile.level
for f in self.htmlfiles:
name = os.path.basename(f.path)
name = os.path.splitext(name)[0] + '.xhtml'
if name in self.htmlfile_map.values():
name = os.path.splitext(name)[0] + '_cr_%d'%save_counter + os.path.splitext(name)[1]
save_counter += 1
self.htmlfile_map[f.path] = name
self.parse_html()
# Handle <image> tags inside embedded <svg>
# At least one source of EPUB files (Penguin) uses xlink:href
# without declaring the xlink namespace
for image in self.root.xpath('//image'):
for attr in image.attrib.keys():
if attr.endswith(':href'):
nhref = self.rewrite_links(image.get(attr))
image.set(attr, nhref)
self.root.rewrite_links(self.rewrite_links, resolve_base_href=False)
for bad in ('xmlns', 'lang', 'xml:lang'): # lxml also adds these attributes for XHTML documents, leading to duplicates
if self.root.get(bad, None) is not None:
self.root.attrib.pop(bad)
def save_path(self):
return os.path.join(self.tdir, self.htmlfile_map[self.htmlfile.path])
def declare_xhtml_namespace(self, match):
if not match.group('raw'):
return '<html xmlns="http://www.w3.org/1999/xhtml">'
raw = match.group('raw')
m = re.search(r'(?i)xmlns\s*=\s*[\'"](?P<uri>[^"\']*)[\'"]', raw)
if not m:
return '<html xmlns="http://www.w3.org/1999/xhtml" %s>'%raw
else:
return match.group().replace(m.group('uri'), "http://www.w3.org/1999/xhtml")
def save(self):
'''
Save processed HTML into the content directory.
Should be called after all HTML processing is finished.
'''
ans = tostring(self.root, pretty_print=self.opts.pretty_print)
ans = re.sub(r'(?i)<\s*html(?P<raw>\s+[^>]*){0,1}>', self.declare_xhtml_namespace, ans[:1000]) + ans[1000:]
ans = re.compile(r'<head>', re.IGNORECASE).sub('<head>\n\t<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n', ans[:1000])+ans[1000:]
self.root.set('xmlns', 'http://www.w3.org/1999/xhtml')
self.root.set('xmlns:xlink', 'http://www.w3.org/1999/xlink')
for svg in self.root.xpath('//svg'):
svg.set('xmlns', 'http://www.w3.org/2000/svg')
ans = tostring(self.root, pretty_print=self.opts.pretty_print)
ans = re.compile(r'<head>', re.IGNORECASE).sub('<head>\n\t<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n', ans[:1000])+ans[1000:]
with open(self.save_path(), 'wb') as f:
f.write(ans)
return f.name

View File

@ -46,9 +46,10 @@ class SVGRasterizer(object):
data = QByteArray(xml2str(elem))
svg = QSvgRenderer(data)
size = svg.defaultSize()
view_box = elem.get('viewBox', elem.get('viewbox', None))
if size.width() == 100 and size.height() == 100 \
and 'viewBox' in elem.attrib:
box = [float(x) for x in elem.attrib['viewBox'].split()]
and view_box is not None:
box = [float(x) for x in view_box.split()]
size.setWidth(box[2] - box[0])
size.setHeight(box[3] - box[1])
if width or height:

View File

@ -63,7 +63,8 @@ class Main(MainWindow, Ui_MainWindow):
p.end()
self.default_thumbnail = (pixmap.width(), pixmap.height(), pixmap_to_data(pixmap))
def __init__(self, single_instance, opts, parent=None):
def __init__(self, single_instance, opts, actions, parent=None):
self.preferences_action, self.quit_action = actions
MainWindow.__init__(self, opts, parent)
# Initialize fontconfig in a separate thread as this can be a lengthy
# process if run for the first time on this machine
@ -100,7 +101,6 @@ class Main(MainWindow, Ui_MainWindow):
self.system_tray_menu = QMenu()
self.restore_action = self.system_tray_menu.addAction(QIcon(':/images/page.svg'), _('&Restore'))
self.donate_action = self.system_tray_menu.addAction(QIcon(':/images/donate.svg'), _('&Donate'))
self.quit_action = QAction(QIcon(':/images/window-close.svg'), _('&Quit'), self)
self.addAction(self.quit_action)
self.action_restart = QAction(_('&Restart'), self)
self.addAction(self.action_restart)
@ -242,6 +242,7 @@ class Main(MainWindow, Ui_MainWindow):
self.tool_bar.setContextMenuPolicy(Qt.PreventContextMenu)
QObject.connect(self.config_button, SIGNAL('clicked(bool)'), self.do_config)
self.connect(self.preferences_action, SIGNAL('triggered(bool)'), self.do_config)
QObject.connect(self.advanced_search_button, SIGNAL('clicked(bool)'), self.do_advanced_search)
####################### Library view ########################
@ -1547,6 +1548,7 @@ def main(args=sys.argv):
prefs.set('library_path', opts.with_library)
print 'Using library at', prefs['library_path']
app = Application(args)
actions = tuple(Main.create_application_menubar())
app.setWindowIcon(QIcon(':/library'))
QCoreApplication.setOrganizationName(ORG_NAME)
QCoreApplication.setApplicationName(APP_UID)
@ -1561,7 +1563,7 @@ def main(args=sys.argv):
'<p>%s is already running. %s</p>'%(__appname__, extra))
return 1
initialize_file_icon_provider()
main = Main(single_instance, opts)
main = Main(single_instance, opts, actions)
sys.excepthook = main.unhandled_exception
if len(args) > 1:
main.add_filesystem_book(args[1])

View File

@ -3,7 +3,8 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import StringIO, traceback, sys
from PyQt4.Qt import QMainWindow, QString, Qt, QFont, QCoreApplication, SIGNAL
from PyQt4.Qt import QMainWindow, QString, Qt, QFont, QCoreApplication, SIGNAL,\
QAction, QMenu, QMenuBar, QIcon
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
from calibre.utils.config import OptionParser
@ -34,6 +35,27 @@ class DebugWindow(ConversionErrorDialog):
class MainWindow(QMainWindow):
_menu_bar = None
@classmethod
def create_application_menubar(cls):
mb = QMenuBar(None)
menu = QMenu()
for action in cls.get_menubar_actions():
menu.addAction(action)
yield action
mb.addMenu(menu)
cls._menu_bar = mb
@classmethod
def get_menubar_actions(cls):
preferences_action = QAction(QIcon(':/images/config.svg'), _('&Preferences'), None)
quit_action = QAction(QIcon(':/images/window-close.svg'), _('&Quit'), None)
preferences_action.setMenuRole(QAction.PreferencesRole)
quit_action.setMenuRole(QAction.QuitRole)
return preferences_action, quit_action
def __init__(self, opts, parent=None):
QMainWindow.__init__(self, parent)
app = QCoreApplication.instance()

View File

@ -158,21 +158,27 @@ class WorkerMother(object):
self.executable = os.path.join(os.path.dirname(sys.executable),
'calibre-parallel.exe' if isfrozen else 'Scripts\\calibre-parallel.exe')
elif isosx:
self.executable = sys.executable
self.executable = self.gui_executable = sys.executable
self.prefix = ''
if isfrozen:
fd = getattr(sys, 'frameworks_dir')
contents = os.path.dirname(fd)
resources = os.path.join(contents, 'Resources')
sp = os.path.join(resources, 'lib', 'python'+sys.version[:3], 'site-packages.zip')
self.gui_executable = os.path.join(contents, 'MacOS',
os.path.basename(sys.executable))
contents = os.path.join(contents, 'console.app', 'Contents')
self.executable = os.path.join(contents, 'MacOS',
os.path.basename(sys.executable))
resources = os.path.join(contents, 'Resources')
fd = os.path.join(contents, 'Frameworks')
sp = os.path.join(resources, 'lib', 'python'+sys.version[:3], 'site-packages.zip')
self.prefix += 'import sys; sys.frameworks_dir = "%s"; sys.frozen = "macosx_app"; '%fd
self.prefix += 'sys.path.insert(0, %s); '%repr(sp)
if fd not in os.environ['PATH']:
self.env['PATH'] = os.environ['PATH']+':'+fd
self.env['PYTHONHOME'] = resources
self.env['MAGICK_HOME'] = os.path.join(getattr(sys, 'frameworks_dir'), 'ImageMagick')
self.env['DYLD_LIBRARY_PATH'] = os.path.join(getattr(sys, 'frameworks_dir'), 'ImageMagick', 'lib')
self.env['MAGICK_HOME'] = os.path.join(fd, 'ImageMagick')
self.env['DYLD_LIBRARY_PATH'] = os.path.join(fd, 'ImageMagick', 'lib')
else:
self.executable = os.path.join(getattr(sys, 'frozen_path'), 'calibre-parallel') \
if isfrozen else 'calibre-parallel'
@ -219,7 +225,8 @@ class WorkerMother(object):
def spawn_free_spirit_osx(self, arg, type='free_spirit'):
script = 'from calibre.parallel import main; main(args=["calibre-parallel", %s]);'%repr(arg)
cmdline = [self.executable, '-c', self.prefix+script]
exe = self.gui_executable if type == 'free_spirit' else self.executable
cmdline = [exe, '-c', self.prefix+script]
child = WorkerStatus(subprocess.Popen(cmdline, env=self.get_env()))
atexit.register(self.cleanup_child_linux, child)
return child