From 73753b67d882e733bf619011176d6b35580efa45 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 May 2010 21:35:00 -0600 Subject: [PATCH] Move mobile server templates to lxml from genshi --- src/calibre/__init__.py | 14 ++ src/calibre/gui2/__init__.py | 13 -- src/calibre/gui2/widgets.py | 5 +- src/calibre/library/server/mobile.py | 249 +++++++++++++++++---------- 4 files changed, 171 insertions(+), 110 deletions(-) diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index e44f8d8ec6..ff4bab6a9a 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -451,6 +451,20 @@ def prepare_string_for_xml(raw, attribute=False): def isbytestring(obj): return isinstance(obj, (str, bytes)) +def human_readable(size): + """ Convert a size in bytes into a human readable form """ + divisor, suffix = 1, "B" + for i, candidate in enumerate(('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')): + if size < 1024**(i+1): + divisor, suffix = 1024**(i), candidate + break + size = str(float(size)/divisor) + if size.find(".") > -1: + size = size[:size.find(".")+2] + if size.endswith('.0'): + size = size[:-2] + return size + " " + suffix + if isosx: import glob, shutil fdir = os.path.expanduser('~/.fonts') diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 0cf565c928..3ee5e67b6b 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -229,19 +229,6 @@ def info_dialog(parent, title, msg, det_msg='', show=False): return d -def human_readable(size): - """ Convert a size in bytes into a human readable form """ - divisor, suffix = 1, "B" - for i, candidate in enumerate(('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')): - if size < 1024**(i+1): - divisor, suffix = 1024**(i), candidate - break - size = str(float(size)/divisor) - if size.find(".") > -1: - size = size[:size.find(".")+2] - if size.endswith('.0'): - size = size[:-2] - return size + " " + suffix class Dispatcher(QObject): '''Convenience class to ensure that a function call always happens in the diff --git a/src/calibre/gui2/widgets.py b/src/calibre/gui2/widgets.py index 8083cd4ba0..093fa3fc5c 100644 --- a/src/calibre/gui2/widgets.py +++ b/src/calibre/gui2/widgets.py @@ -13,11 +13,10 @@ from PyQt4.Qt import QListView, QIcon, QFont, QLabel, QListWidget, \ QAbstractButton, QPainter, QLineEdit, QComboBox, \ QMenu, QStringListModel, QCompleter, QStringList -from calibre.gui2 import human_readable, NONE, \ - error_dialog, pixmap_to_data, dynamic +from calibre.gui2 import NONE, error_dialog, pixmap_to_data, dynamic from calibre.gui2.filename_pattern_ui import Ui_Form -from calibre import fit_image +from calibre import fit_image, human_readable from calibre.utils.fonts import fontconfig from calibre.ebooks import BOOK_EXTENSIONS from calibre.ebooks.metadata.meta import metadata_from_filename diff --git a/src/calibre/library/server/mobile.py b/src/calibre/library/server/mobile.py index afb31815d5..6a227a6366 100644 --- a/src/calibre/library/server/mobile.py +++ b/src/calibre/library/server/mobile.py @@ -5,34 +5,143 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import re, copy +import re import __builtin__ import cherrypy +from lxml import html +from lxml.html.builder import HTML, HEAD, TITLE, STYLE, LINK, DIV, IMG, BODY, \ + OPTION, SELECT, INPUT, FORM, SPAN, TABLE, TR, TD, A, HR -from calibre.utils.genshi.template import MarkupTemplate from calibre.library.server.utils import strftime from calibre.ebooks.metadata import fmt_sidx +from calibre.constants import __appname__ +from calibre import human_readable -# Templates {{{ -MOBILE_BOOK = '''\ - - - - - - - ${format.lower()}  - - ${r[FM['title']]}${(' ['+r[FM['series']]+'-'+r[FM['series_index']]+']') if r[FM['series']] else ''} by ${authors} - ${r[FM['size']]/1024}k - ${r[FM['publisher']] if r[FM['publisher']] else ''} ${pubdate} ${'['+r[FM['tags']]+']' if r[FM['tags']] else ''} - - -''' +def CLASS(*args, **kwargs): # class is a reserved word in Python + kwargs['class'] = ' '.join(args) + return kwargs -MOBILE = MarkupTemplate('''\ - - - - - - - - - -
- - - ${Markup(book)} - -
- - -''') - -# }}} class MobileServer(object): 'A view optimized for browsers in mobile devices' @@ -195,26 +251,31 @@ class MobileServer(object): except ValueError: raise cherrypy.HTTPError(400, 'num: %s is not an integer'%num) ids = self.db.data.parse(search) if search and search.strip() else self.db.data.universal_set() - ids = sorted(ids) FM = self.db.FIELD_MAP - items = copy.deepcopy([r for r in iter(self.db) if r[FM['id']] in ids]) + items = [r for r in iter(self.db) if r[FM['id']] in ids] if sort is not None: self.sort(items, sort, (order.lower().strip() == 'ascending')) - book, books = MarkupTemplate(MOBILE_BOOK), [] + books = [] for record in items[(start-1):(start-1)+num]: - if record[FM['formats']] is None: - record[FM['formats']] = '' - if record[FM['size']] is None: - record[FM['size']] = 0 + book = {'formats':record[FM['formats']], 'size':record[FM['size']]} + if not book['formats']: + book['formats'] = '' + if not book['size']: + book['size'] = 0 + book['size'] = human_readable(book['size']) + aus = record[FM['authors']] if record[FM['authors']] else __builtin__._('Unknown') authors = '|'.join([i.replace('|', ',') for i in aus.split(',')]) - record[FM['series_index']] = \ - fmt_sidx(float(record[FM['series_index']])) - ts, pd = strftime('%Y/%m/%d %H:%M:%S', record[FM['timestamp']]), \ - strftime('%Y/%m/%d %H:%M:%S', record[FM['pubdate']]) - books.append(book.generate(r=record, authors=authors, timestamp=ts, - pubdate=pd, FM=FM).render('xml').decode('utf-8')) + book['authors'] = authors + book['series_index'] = fmt_sidx(float(record[FM['series_index']])) + book['series'] = record[FM['series']] + book['tags'] = record[FM['tags']] + book['title'] = record[FM['title']] + for x in ('timestamp', 'pubdate'): + book[x] = strftime('%Y/%m/%d %H:%M:%S', record[FM[x]]) + book['id'] = record[FM['id']] + books.append(book) updated = self.db.last_modified() cherrypy.response.headers['Content-Type'] = 'text/html; charset=utf-8' @@ -223,8 +284,8 @@ class MobileServer(object): url_base = "/mobile?search=" + search+";order="+order+";sort="+sort+";num="+str(num) - return MOBILE.generate(books=books, start=start, updated=updated, - search=search, sort=sort, order=order, num=num, FM=FM, - total=len(ids), url_base=url_base).render('html') - + return html.tostring(build_index(books, num, search, sort, order, + start, len(ids), url_base), + encoding='utf-8', include_meta_content_type=True, + pretty_print=True)