More refactoring for the new resource system
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 471 B After Width: | Height: | Size: 471 B |
Before Width: | Height: | Size: 335 B After Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 267 B |
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
@ -38,7 +38,6 @@ class FB2Input(InputFormatPlugin):
|
|||||||
|
|
||||||
def convert(self, stream, options, file_ext, log,
|
def convert(self, stream, options, file_ext, log,
|
||||||
accelerators):
|
accelerators):
|
||||||
from calibre.resources import fb2_xsl
|
|
||||||
from calibre.ebooks.metadata.opf2 import OPFCreator
|
from calibre.ebooks.metadata.opf2 import OPFCreator
|
||||||
from calibre.ebooks.metadata.meta import get_metadata
|
from calibre.ebooks.metadata.meta import get_metadata
|
||||||
from calibre.ebooks.oeb.base import XLINK_NS
|
from calibre.ebooks.oeb.base import XLINK_NS
|
||||||
@ -49,7 +48,7 @@ class FB2Input(InputFormatPlugin):
|
|||||||
doc = etree.parse(stream, parser)
|
doc = etree.parse(stream, parser)
|
||||||
self.extract_embedded_content(doc)
|
self.extract_embedded_content(doc)
|
||||||
log.debug('Converting XML to HTML...')
|
log.debug('Converting XML to HTML...')
|
||||||
ss = fb2_xsl
|
ss = open(P('templates/fb2.xsl'), 'rb').read()
|
||||||
if options.no_inline_fb2_toc:
|
if options.no_inline_fb2_toc:
|
||||||
log('Disabling generation of inline FB2 TOC')
|
log('Disabling generation of inline FB2 TOC')
|
||||||
ss = re.compile(r'<!-- BUILD TOC -->.*<!-- END BUILD TOC -->',
|
ss = re.compile(r'<!-- BUILD TOC -->.*<!-- END BUILD TOC -->',
|
||||||
|
@ -503,8 +503,8 @@ class OPFCreator(MetaInformation):
|
|||||||
self.guide.set_basedir(self.base_path)
|
self.guide.set_basedir(self.base_path)
|
||||||
|
|
||||||
def render(self, opf_stream, ncx_stream=None, ncx_manifest_entry=None):
|
def render(self, opf_stream, ncx_stream=None, ncx_manifest_entry=None):
|
||||||
from calibre.resources import opf_template
|
|
||||||
from calibre.utils.genshi.template import MarkupTemplate
|
from calibre.utils.genshi.template import MarkupTemplate
|
||||||
|
opf_template = open(P('templates/opf.xml'), 'rb').read()
|
||||||
template = MarkupTemplate(opf_template)
|
template = MarkupTemplate(opf_template)
|
||||||
if self.manifest:
|
if self.manifest:
|
||||||
self.manifest.set_basedir(self.base_path)
|
self.manifest.set_basedir(self.base_path)
|
||||||
|
@ -930,8 +930,8 @@ class OPFCreator(MetaInformation):
|
|||||||
|
|
||||||
def render(self, opf_stream=sys.stdout, ncx_stream=None,
|
def render(self, opf_stream=sys.stdout, ncx_stream=None,
|
||||||
ncx_manifest_entry=None, encoding=None):
|
ncx_manifest_entry=None, encoding=None):
|
||||||
from calibre.resources import opf_template
|
|
||||||
from calibre.utils.genshi.template import MarkupTemplate
|
from calibre.utils.genshi.template import MarkupTemplate
|
||||||
|
opf_template = open(P('templates/opf.xml'), 'rb').read()
|
||||||
if encoding is None:
|
if encoding is None:
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
template = MarkupTemplate(opf_template)
|
template = MarkupTemplate(opf_template)
|
||||||
|
@ -207,8 +207,8 @@ class TOC(list):
|
|||||||
self.add_item(href, fragment, txt)
|
self.add_item(href, fragment, txt)
|
||||||
|
|
||||||
def render(self, stream, uid):
|
def render(self, stream, uid):
|
||||||
from calibre.resources import ncx_template
|
|
||||||
from calibre.utils.genshi.template import MarkupTemplate
|
from calibre.utils.genshi.template import MarkupTemplate
|
||||||
|
ncx_template = open(P('templates/ncx.xml'), 'rb').read()
|
||||||
doctype = ('ncx', "-//NISO//DTD ncx 2005-1//EN", "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd")
|
doctype = ('ncx', "-//NISO//DTD ncx 2005-1//EN", "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd")
|
||||||
template = MarkupTemplate(ncx_template)
|
template = MarkupTemplate(ncx_template)
|
||||||
raw = template.generate(uid=uid, toc=self, __appname__=__appname__)
|
raw = template.generate(uid=uid, toc=self, __appname__=__appname__)
|
||||||
|
@ -51,14 +51,13 @@ class MOBIOutput(OutputFormatPlugin):
|
|||||||
found = 'masthead' in self.oeb.guide
|
found = 'masthead' in self.oeb.guide
|
||||||
if not found:
|
if not found:
|
||||||
self.oeb.log.debug('No masthead found, generating default one...')
|
self.oeb.log.debug('No masthead found, generating default one...')
|
||||||
from calibre.resources import server_resources
|
|
||||||
try:
|
try:
|
||||||
from PIL import Image as PILImage
|
from PIL import Image as PILImage
|
||||||
PILImage
|
PILImage
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import Image as PILImage
|
import Image as PILImage
|
||||||
|
|
||||||
raw = StringIO(server_resources['calibre_banner.png'])
|
raw = open(P('content_server/calibre_banner.png'), 'rb')
|
||||||
im = PILImage.open(raw)
|
im = PILImage.open(raw)
|
||||||
of = StringIO()
|
of = StringIO()
|
||||||
im.save(of, 'GIF')
|
im.save(of, 'GIF')
|
||||||
|
@ -24,8 +24,8 @@ from lxml.cssselect import css_to_xpath, ExpressionError, SelectorSyntaxError
|
|||||||
from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES
|
from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES
|
||||||
from calibre.ebooks.oeb.base import XPNSMAP, xpath, urlnormalize
|
from calibre.ebooks.oeb.base import XPNSMAP, xpath, urlnormalize
|
||||||
from calibre.ebooks.oeb.profile import PROFILES
|
from calibre.ebooks.oeb.profile import PROFILES
|
||||||
from calibre.resources import html_css
|
|
||||||
|
|
||||||
|
html_css = open(P('templates/html.css'), 'rb').read()
|
||||||
XHTML_CSS_NAMESPACE = '@namespace "%s";\n' % XHTML_NS
|
XHTML_CSS_NAMESPACE = '@namespace "%s";\n' % XHTML_NS
|
||||||
HTML_CSS_STYLESHEET = cssutils.parseString(html_css)
|
HTML_CSS_STYLESHEET = cssutils.parseString(html_css)
|
||||||
HTML_CSS_STYLESHEET.namespaces['h'] = XHTML_NS
|
HTML_CSS_STYLESHEET.namespaces['h'] = XHTML_NS
|
||||||
|
@ -8,11 +8,12 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import os, math, re, glob
|
import os, math, re, glob
|
||||||
from PyQt4.Qt import QWidget, QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, \
|
from PyQt4.Qt import QWidget, QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, \
|
||||||
QPainter, QPalette, QBrush, QFontDatabase, QDialog, \
|
QPainter, QPalette, QBrush, QFontDatabase, QDialog, \
|
||||||
QColor, QPoint, QImage, QRegion, \
|
QColor, QPoint, QImage, QRegion, QVariant, \
|
||||||
QFont, QObject, QApplication, pyqtSignature
|
QFont, QObject, QApplication, pyqtSignature
|
||||||
from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
||||||
|
|
||||||
from calibre.utils.config import Config, StringConfig
|
from calibre.utils.config import Config, StringConfig
|
||||||
|
from calibre.utils.localization import get_language
|
||||||
from calibre.gui2.viewer.config_ui import Ui_Dialog
|
from calibre.gui2.viewer.config_ui import Ui_Dialog
|
||||||
from calibre.gui2.viewer.js import bookmarks, referencing, hyphenation
|
from calibre.gui2.viewer.js import bookmarks, referencing, hyphenation
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
@ -86,12 +87,19 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
self.css.setPlainText(opts.user_css)
|
self.css.setPlainText(opts.user_css)
|
||||||
self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
|
self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
|
||||||
self.max_view_width.setValue(opts.max_view_width)
|
self.max_view_width.setValue(opts.max_view_width)
|
||||||
from calibre.resources import hyphenate
|
pats = [os.path.basename(x).split('.')[0] for x in
|
||||||
for x in sorted(hyphenate['languages'].split(',')):
|
glob.glob(P('viewer/hyphenate/patterns/*.js'))]
|
||||||
self.hyphenate_default_lang.addItem(x)
|
names = list(map(get_language, pats))
|
||||||
idx = self.hyphenate_default_lang.findText(opts.hyphenate_default_lang)
|
pmap = {}
|
||||||
if idx == -1:
|
for i in range(len(pats)):
|
||||||
idx = self.hyphenate_default_lang.findText('en')
|
pmap[names[i]] = pats[i]
|
||||||
|
for x in sorted(names):
|
||||||
|
self.hyphenate_default_lang.addItem(x, QVariant(pmap[x]))
|
||||||
|
try:
|
||||||
|
idx = pats.index(opts.hyphenate_default_lang)
|
||||||
|
except ValueError:
|
||||||
|
idx = pats.index('en')
|
||||||
|
idx = self.hyphenate_default_lang.findText(names[idx])
|
||||||
self.hyphenate_default_lang.setCurrentIndex(idx)
|
self.hyphenate_default_lang.setCurrentIndex(idx)
|
||||||
self.hyphenate.setChecked(opts.hyphenate)
|
self.hyphenate.setChecked(opts.hyphenate)
|
||||||
self.hyphenate_default_lang.setEnabled(opts.hyphenate)
|
self.hyphenate_default_lang.setEnabled(opts.hyphenate)
|
||||||
@ -109,8 +117,9 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
c.set('remember_window_size', self.opt_remember_window_size.isChecked())
|
c.set('remember_window_size', self.opt_remember_window_size.isChecked())
|
||||||
c.set('max_view_width', int(self.max_view_width.value()))
|
c.set('max_view_width', int(self.max_view_width.value()))
|
||||||
c.set('hyphenate', self.hyphenate.isChecked())
|
c.set('hyphenate', self.hyphenate.isChecked())
|
||||||
|
idx = self.hyphenate_default_lang.currentIndex()
|
||||||
c.set('hyphenate_default_lang',
|
c.set('hyphenate_default_lang',
|
||||||
self.hyphenate_default_lang.currentText())
|
str(self.hyphenate_default_lang.itemData(idx).toString()))
|
||||||
return QDialog.accept(self, *args)
|
return QDialog.accept(self, *args)
|
||||||
|
|
||||||
|
|
||||||
@ -184,7 +193,10 @@ class Document(QWebPage):
|
|||||||
|
|
||||||
def load_javascript_libraries(self):
|
def load_javascript_libraries(self):
|
||||||
self.mainFrame().addToJavaScriptWindowObject("py_bridge", self)
|
self.mainFrame().addToJavaScriptWindowObject("py_bridge", self)
|
||||||
from calibre.resources import jquery, jquery_scrollTo, hyphenate
|
jquery = open(P('content_server/jquery.js'), 'rb').read()
|
||||||
|
jquery_scrollTo = open(P('viewer/jquery_scrollTo.js'), 'rb').read()
|
||||||
|
hyphenator = open(P('viewer/hyphenate/Hyphenator.js'),
|
||||||
|
'rb').read().decode('utf-8')
|
||||||
self.javascript(jquery)
|
self.javascript(jquery)
|
||||||
self.javascript(jquery_scrollTo)
|
self.javascript(jquery_scrollTo)
|
||||||
self.javascript(bookmarks)
|
self.javascript(bookmarks)
|
||||||
@ -195,11 +207,14 @@ class Document(QWebPage):
|
|||||||
if not lang:
|
if not lang:
|
||||||
lang = default_lang
|
lang = default_lang
|
||||||
lang = lang.lower()[:2]
|
lang = lang.lower()[:2]
|
||||||
if lang not in hyphenate['languages']:
|
self.javascript(hyphenator)
|
||||||
|
p = P('viewer/hyphenate/patterns/%s.js'%lang)
|
||||||
|
if not os.path.exists(p):
|
||||||
lang = default_lang
|
lang = default_lang
|
||||||
|
p = P('viewer/hyphenate/patterns/%s.js'%lang)
|
||||||
|
self.javascript(open(p, 'rb').read().decode('utf-8'))
|
||||||
self.loaded_lang = lang
|
self.loaded_lang = lang
|
||||||
self.javascript(hyphenate['Hyphenator.js'].decode('utf-8'))
|
|
||||||
self.javascript(hyphenate[lang+'.js'].decode('utf-8'))
|
|
||||||
|
|
||||||
@pyqtSignature("")
|
@pyqtSignature("")
|
||||||
def animated_scroll_done(self):
|
def animated_scroll_done(self):
|
||||||
|
@ -16,7 +16,6 @@ from PyQt4.Qt import QWizard, QWizardPage, QPixmap, Qt, QAbstractListModel, \
|
|||||||
from calibre import __appname__, patheq
|
from calibre import __appname__, patheq
|
||||||
from calibre.library.database2 import LibraryDatabase2
|
from calibre.library.database2 import LibraryDatabase2
|
||||||
from calibre.library.move import MoveLibrary
|
from calibre.library.move import MoveLibrary
|
||||||
from calibre.resources import server_resources
|
|
||||||
from calibre.constants import filesystem_encoding
|
from calibre.constants import filesystem_encoding
|
||||||
from calibre.gui2.wizard.send_email import smtp_prefs
|
from calibre.gui2.wizard.send_email import smtp_prefs
|
||||||
from calibre.gui2.wizard.device_ui import Ui_WizardPage as DeviceUI
|
from calibre.gui2.wizard.device_ui import Ui_WizardPage as DeviceUI
|
||||||
@ -528,7 +527,7 @@ class Wizard(QWizard):
|
|||||||
QWizard.__init__(self, parent)
|
QWizard.__init__(self, parent)
|
||||||
self.setWindowTitle(__appname__+' '+_('welcome wizard'))
|
self.setWindowTitle(__appname__+' '+_('welcome wizard'))
|
||||||
p = QPixmap()
|
p = QPixmap()
|
||||||
p.loadFromData(server_resources['calibre.png'])
|
p.loadFromData(open(P('content_server/calibre.png'), 'rb').read())
|
||||||
self.setPixmap(self.LogoPixmap, p.scaledToHeight(80,
|
self.setPixmap(self.LogoPixmap, p.scaledToHeight(80,
|
||||||
Qt.SmoothTransformation))
|
Qt.SmoothTransformation))
|
||||||
self.setPixmap(self.WatermarkPixmap,
|
self.setPixmap(self.WatermarkPixmap,
|
||||||
|
@ -453,7 +453,7 @@ class LibraryDatabase2(LibraryDatabase):
|
|||||||
loc=FIELD_MAP['comments' if prop == 'comment' else prop]))
|
loc=FIELD_MAP['comments' if prop == 'comment' else prop]))
|
||||||
|
|
||||||
def initialize_database(self):
|
def initialize_database(self):
|
||||||
from calibre.resources import metadata_sqlite
|
metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read()
|
||||||
self.conn.executescript(metadata_sqlite)
|
self.conn.executescript(metadata_sqlite)
|
||||||
self.user_version = 1
|
self.user_version = 1
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ from calibre.constants import __version__, __appname__
|
|||||||
from calibre.utils.genshi.template import MarkupTemplate
|
from calibre.utils.genshi.template import MarkupTemplate
|
||||||
from calibre import fit_image, guess_type, prepare_string_for_xml, \
|
from calibre import fit_image, guess_type, prepare_string_for_xml, \
|
||||||
strftime as _strftime
|
strftime as _strftime
|
||||||
from calibre.resources import jquery, server_resources, build_time
|
|
||||||
from calibre.library import server_config as config
|
from calibre.library import server_config as config
|
||||||
from calibre.library.database2 import LibraryDatabase2, FIELD_MAP
|
from calibre.library.database2 import LibraryDatabase2, FIELD_MAP
|
||||||
from calibre.utils.config import config_dir
|
from calibre.utils.config import config_dir
|
||||||
@ -33,9 +32,6 @@ from calibre.utils.mdns import publish as publish_zeroconf, \
|
|||||||
stop_server as stop_zeroconf
|
stop_server as stop_zeroconf
|
||||||
from calibre.ebooks.metadata import fmt_sidx, title_sort
|
from calibre.ebooks.metadata import fmt_sidx, title_sort
|
||||||
|
|
||||||
build_time = datetime.strptime(build_time, '%d %m %Y %H%M%S')
|
|
||||||
server_resources['jquery.js'] = jquery
|
|
||||||
|
|
||||||
def strftime(fmt='%Y/%m/%d %H:%M:%S', dt=None):
|
def strftime(fmt='%Y/%m/%d %H:%M:%S', dt=None):
|
||||||
if not hasattr(dt, 'timetuple'):
|
if not hasattr(dt, 'timetuple'):
|
||||||
dt = datetime.now()
|
dt = datetime.now()
|
||||||
@ -208,6 +204,9 @@ class LibraryServer(object):
|
|||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.max_cover_width, self.max_cover_height = \
|
self.max_cover_width, self.max_cover_height = \
|
||||||
map(int, self.opts.max_cover.split('x'))
|
map(int, self.opts.max_cover.split('x'))
|
||||||
|
path = P('content_server')
|
||||||
|
self.build_time = datetime.fromtimestamp(os.stat(path).st_mtime)
|
||||||
|
self.default_cover = open(P('content_server/default_cover.jpg'), 'rb').read()
|
||||||
|
|
||||||
cherrypy.config.update({
|
cherrypy.config.update({
|
||||||
'log.screen' : opts.develop,
|
'log.screen' : opts.develop,
|
||||||
@ -280,10 +279,11 @@ class LibraryServer(object):
|
|||||||
def get_cover(self, id, thumbnail=False):
|
def get_cover(self, id, thumbnail=False):
|
||||||
cover = self.db.cover(id, index_is_id=True, as_file=False)
|
cover = self.db.cover(id, index_is_id=True, as_file=False)
|
||||||
if cover is None:
|
if cover is None:
|
||||||
cover = server_resources['default_cover.jpg']
|
cover = self.default_cover
|
||||||
cherrypy.response.headers['Content-Type'] = 'image/jpeg'
|
cherrypy.response.headers['Content-Type'] = 'image/jpeg'
|
||||||
path = getattr(cover, 'name', False)
|
path = getattr(cover, 'name', False)
|
||||||
updated = datetime.utcfromtimestamp(os.stat(path).st_mtime) if path and os.access(path, os.R_OK) else build_time
|
updated = datetime.utcfromtimestamp(os.stat(path).st_mtime) if path and \
|
||||||
|
os.access(path, os.R_OK) else self.build_time
|
||||||
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
|
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
|
||||||
try:
|
try:
|
||||||
f = cStringIO.StringIO(cover)
|
f = cStringIO.StringIO(cover)
|
||||||
@ -571,17 +571,14 @@ class LibraryServer(object):
|
|||||||
'html' : 'text/html',
|
'html' : 'text/html',
|
||||||
'' : 'application/octet-stream',
|
'' : 'application/octet-stream',
|
||||||
}[name.rpartition('.')[-1].lower()]
|
}[name.rpartition('.')[-1].lower()]
|
||||||
cherrypy.response.headers['Last-Modified'] = self.last_modified(build_time)
|
cherrypy.response.headers['Last-Modified'] = self.last_modified(self.build_time)
|
||||||
if self.opts.develop and not getattr(sys, 'frozen', False) and \
|
path = P('content_server/'+name)
|
||||||
name in ('gui.js', 'gui.css', 'index.html'):
|
if not os.path.exists(path):
|
||||||
path = os.path.join(os.path.dirname(__file__), 'static', name)
|
raise cherrypy.HTTPError(404, '%s not found'%name)
|
||||||
|
if self.opts.develop:
|
||||||
lm = datetime.fromtimestamp(os.stat(path).st_mtime)
|
lm = datetime.fromtimestamp(os.stat(path).st_mtime)
|
||||||
cherrypy.response.headers['Last-Modified'] = self.last_modified(lm)
|
cherrypy.response.headers['Last-Modified'] = self.last_modified(lm)
|
||||||
return open(path, 'rb').read()
|
return open(path, 'rb').read()
|
||||||
else:
|
|
||||||
if server_resources.has_key(name):
|
|
||||||
return server_resources[name]
|
|
||||||
raise cherrypy.HTTPError(404, '%s not found'%name)
|
|
||||||
|
|
||||||
def start_threaded_server(db, opts):
|
def start_threaded_server(db, opts):
|
||||||
server = LibraryServer(db, opts, embedded=True)
|
server = LibraryServer(db, opts, embedded=True)
|
||||||
|