Fine tune the screen height for LRF conversions and drop the prs500-unsafe profile. Make GUI not die when an invalid option i passed to the ebook converter.

This commit is contained in:
Kovid Goyal 2008-01-15 20:35:06 +00:00
parent 98462ab969
commit ef48bcc3c1
9 changed files with 95 additions and 54 deletions

View File

@ -21,6 +21,7 @@ __appname__ = 'libprs500'
import sys, os, logging, mechanize, locale, cStringIO, re import sys, os, logging, mechanize, locale, cStringIO, re
from gettext import GNUTranslations from gettext import GNUTranslations
from math import floor from math import floor
from optparse import OptionParser as _OptionParser
from ttfquery import findsystem, describe from ttfquery import findsystem, describe
@ -63,6 +64,22 @@ def setup_cli_handlers(logger, level):
logger.addHandler(handler) logger.addHandler(handler)
class OptionParser(_OptionParser):
def __init__(self,
usage='%prog [options] filename',
version=__appname__+' '+__version__,
epilog=_('Created by ')+__author__,
gui_mode=False,
**kwds):
_OptionParser.__init__(self, usage=usage, version=version, epilog=epilog, **kwds)
self.gui_mode = gui_mode
def error(self, msg):
if self.gui_mode:
raise Exception(msg)
_OptionParser.error(self, msg)
def load_library(name, cdll): def load_library(name, cdll):
if iswindows: if iswindows:
return cdll.LoadLibrary(name) return cdll.LoadLibrary(name)

View File

@ -17,7 +17,7 @@ This package contains logic to read and write LRF files.
The LRF file format is documented at U{http://www.sven.de/librie/Librie/LrfFormat}. The LRF file format is documented at U{http://www.sven.de/librie/Librie/LrfFormat}.
""" """
import sys, os import sys, os
from optparse import OptionParser, OptionValueError from optparse import OptionValueError
from htmlentitydefs import name2codepoint from htmlentitydefs import name2codepoint
from uuid import uuid4 from uuid import uuid4
@ -29,8 +29,7 @@ from libprs500.ebooks.lrf.pylrs.pylrs import TextBlock, Header, PutObj, \
Paragraph, TextStyle, BlockStyle Paragraph, TextStyle, BlockStyle
from libprs500.ebooks.lrf.fonts import FONT_FILE_MAP from libprs500.ebooks.lrf.fonts import FONT_FILE_MAP
from libprs500.ebooks import ConversionError from libprs500.ebooks import ConversionError
from libprs500 import __appname__, __version__, __author__ from libprs500 import __appname__, __version__, __author__, iswindows, OptionParser
from libprs500 import iswindows
__docformat__ = "epytext" __docformat__ = "epytext"
@ -40,10 +39,10 @@ class LRFParseError(Exception):
class PRS500_PROFILE(object): class PRS500_PROFILE(object):
screen_width = 600 screen_width = 600
screen_height = 765 screen_height = 775
dpi = 166 dpi = 166
# Number of pixels to subtract from screen_height when calculating height of text area # Number of pixels to subtract from screen_height when calculating height of text area
fudge = 18 fudge = 0
font_size = 10 #: Default (in pt) font_size = 10 #: Default (in pt)
parindent = 10 #: Default (in pt) parindent = 10 #: Default (in pt)
line_space = 1.2 #: Default (in pt) line_space = 1.2 #: Default (in pt)
@ -54,14 +53,8 @@ class PRS500_PROFILE(object):
name = 'prs500' name = 'prs500'
class PRS500_PROFILE_UNSAFE(PRS500_PROFILE):
fudge = 0
name = 'prs500-unsafe'
profile_map = { profile_map = {
PRS500_PROFILE.name : PRS500_PROFILE, PRS500_PROFILE.name : PRS500_PROFILE,
PRS500_PROFILE_UNSAFE.name : PRS500_PROFILE_UNSAFE,
} }
def profile_from_string(option, opt_str, value, parser): def profile_from_string(option, opt_str, value, parser):
@ -85,9 +78,8 @@ def font_family(option, opt_str, value, parser):
setattr(parser.values, option.dest, tuple()) setattr(parser.values, option.dest, tuple())
def option_parser(usage): def option_parser(usage, gui_mode=False):
parser = OptionParser(usage=usage, version=__appname__+' '+__version__, parser = OptionParser(usage=usage, gui_mode=gui_mode)
epilog=_('Created by ')+__author__)
metadata = parser.add_option_group('METADATA OPTIONS') metadata = parser.add_option_group('METADATA OPTIONS')
metadata.add_option("-t", "--title", action="store", type="string", default=None,\ metadata.add_option("-t", "--title", action="store", type="string", default=None,\
dest="title", help=_("Set the title. Default: filename.")) dest="title", help=_("Set the title. Default: filename."))
@ -272,7 +264,8 @@ def Book(options, logger, font_delta=0, header=None,
ps['evensidemargin'] = options.left_margin ps['evensidemargin'] = options.left_margin
ps['oddsidemargin'] = options.left_margin ps['oddsidemargin'] = options.left_margin
ps['textwidth'] = profile.screen_width - (options.left_margin + options.right_margin) ps['textwidth'] = profile.screen_width - (options.left_margin + options.right_margin)
ps['textheight'] = profile.screen_height - (options.top_margin + options.bottom_margin) - profile.fudge ps['textheight'] = profile.screen_height - (options.top_margin + options.bottom_margin) \
- profile.fudge
if header: if header:
hdr = Header() hdr = Header()
hb = TextBlock(textStyle=TextStyle(align='foot', hb = TextBlock(textStyle=TextStyle(align='foot',
@ -283,7 +276,9 @@ def Book(options, logger, font_delta=0, header=None,
ps['headheight'] = profile.header_height ps['headheight'] = profile.header_height
ps['header'] = hdr ps['header'] = hdr
ps['topmargin'] = 0 ps['topmargin'] = 0
ps['textheight'] = profile.screen_height - (options.bottom_margin + ps['topmargin'] + ps['headheight'] + profile.fudge) ps['textheight'] = profile.screen_height - (options.bottom_margin + ps['topmargin']) \
- ps['headheight'] - profile.fudge
fontsize = int(10*profile.font_size+font_delta*20) fontsize = int(10*profile.font_size+font_delta*20)
baselineskip = fontsize + 20 baselineskip = fontsize + 20
fonts = find_custom_fonts(options, logger) fonts = find_custom_fonts(options, logger)

View File

@ -12,6 +12,7 @@
## You should have received a copy of the GNU General Public License along ## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc., ## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from libprs500.ebooks import ConversionError
'''Convert any ebook file into a LRF file.''' '''Convert any ebook file into a LRF file.'''
import sys, os, logging, shutil, tempfile, glob import sys, os, logging, shutil, tempfile, glob
@ -125,14 +126,14 @@ def process_file(path, options, logger=None):
return 0 return 0
def main(args=sys.argv, logger=None): def main(args=sys.argv, logger=None, gui_mode=False):
parser = option_parser('''\ parser = option_parser(usage='''\
any2lrf myfile any2lrf myfile
Convert any ebook format into LRF. Supported formats are: Convert any ebook format into LRF. Supported formats are:
LIT, RTF, TXT, HTML, EPUB and PDF. any2lrf will also process a RAR or LIT, RTF, TXT, HTML, EPUB and PDF. any2lrf will also process a RAR or
ZIP archive. ZIP archive.
''') ''', gui_mode=gui_mode)
options, args = parser.parse_args(args) options, args = parser.parse_args(args)
if len(args) != 2: if len(args) != 2:
parser.print_help() parser.print_help()

View File

@ -40,27 +40,42 @@ def get_parser(extension):
class MetaInformation(object): class MetaInformation(object):
'''Convenient encapsulation of book metadata''' '''Convenient encapsulation of book metadata'''
@staticmethod
def copy(mi):
ans = MetaInformation(mi.title, mi.authors)
ans.author_sort = mi.author_sort
ans.title_sort = mi.title_sort
ans.comments = mi.comments
ans.category = mi.category
ans.publisher = mi.publisher
def __init__(self, title, authors): def __init__(self, title, authors):
''' '''
@param title: title or "Unknonw" @param title: title or "Unknown" or a MetaInformation object
@param authors: List of strings or [] @param authors: List of strings or []
''' '''
mi = None
if isinstance(title, MetaInformation):
mi = title
title = mi.title
authors = mi.authors
self.title = title self.title = title
self.author = authors # Needed for backward compatibility self.author = authors # Needed for backward compatibility
#: List of strings or [] #: List of strings or []
self.authors = authors self.authors = authors
#: Sort text for author #: Sort text for author
self.author_sort = None self.author_sort = None if not mi else mi.author_sort
self.title_sort = None self.title_sort = None if not mi else mi.title_sort
self.comments = None self.comments = None if not mi else mi.comments
self.category = None self.category = None if not mi else mi.category
self.publisher = None self.publisher = None if not mi else mi.publisher
self.series = None self.series = None if not mi else mi.series
self.series_index = None self.series_index = None if not mi else mi.series_index
self.rating = None self.rating = None if not mi else mi.rating
self.isbn = None self.isbn = None if not mi else mi.isbn
self.tags = [] self.tags = [] if not mi else mi.tags
self.cover_data = (None, None) #(extension, data) self.cover_data = (None, None) if not mi else mi.cover_data #(extension, data)
def __str__(self): def __str__(self):
ans = u'' ans = u''

View File

@ -26,15 +26,15 @@ from libprs500.ebooks.metadata import MetaInformation
def get_metadata(stream, stream_type='lrf'): def get_metadata(stream, stream_type='lrf'):
if stream_type: stream_type = stream_type.lower() if stream_type: stream_type = stream_type.lower()
if stream_type == 'rtf': if stream_type == 'rtf':
return rtf_metadata(stream) return MetaInformation(rtf_metadata(stream), None)
if stream_type == 'lrf': if stream_type == 'lrf':
return lrf_metadata(stream) return MetaInformation(lrf_metadata(stream), None)
if stream_type == 'pdf': if stream_type == 'pdf':
return pdf_metadata(stream) return MetaInformation(pdf_metadata(stream), None)
if stream_type == 'lit': if stream_type == 'lit':
return lit_metadata(stream) return MetaInformation(lit_metadata(stream), None)
if stream_type == 'epub': if stream_type == 'epub':
return epub_metadata(stream) return MetaInformation(epub_metadata(stream), None)
return MetaInformation(None, None) return MetaInformation(None, None)
def set_metadata(stream, mi, stream_type='lrf'): def set_metadata(stream, mi, stream_type='lrf'):

View File

@ -145,7 +145,9 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
elif isinstance(obj, QTextEdit): elif isinstance(obj, QTextEdit):
obj.setPlainText(cmdline[i+1]) obj.setPlainText(cmdline[i+1])
profile = cmdline[cmdline.index('--profile')+1] profile = cmdline[cmdline.index('--profile')+1]
self.gui_profile.setCurrentIndex(self.gui_profile.findText(profile)) pindex = self.gui_profile.findText(profile)
if pindex >= 0:
self.gui_profile.setCurrentIndex(pindex)
for prepro in self.PREPROCESS_OPTIONS: for prepro in self.PREPROCESS_OPTIONS:
ops = prepro.get_opt_string() ops = prepro.get_opt_string()
if ops in cmdline: if ops in cmdline:

View File

@ -110,6 +110,7 @@ class Main(MainWindow, Ui_MainWindow):
self.closed = False self.closed = False
def configure(self, triggered): def configure(self, triggered):
opts = cPickle.loads(str(QSettings().value('ebook viewer options', QVariant(cPickle.dumps(self.opts))).toString())) opts = cPickle.loads(str(QSettings().value('ebook viewer options', QVariant(cPickle.dumps(self.opts))).toString()))
d = Config(self, opts) d = Config(self, opts)
@ -166,11 +167,16 @@ class Main(MainWindow, Ui_MainWindow):
if not self.renderer.aborted and self.renderer.lrf is not None: if not self.renderer.aborted and self.renderer.lrf is not None:
width, height = self.renderer.lrf.device_info.width, \ width, height = self.renderer.lrf.device_info.width, \
self.renderer.lrf.device_info.height self.renderer.lrf.device_info.height
self.graphics_view.resize_for(width+5, height+5) hdelta = self.viewer_page.size().height() - self.graphics_view.size().height()
from PyQt4.QtGui import QScrollBar
s = QScrollBar(self)
scrollbar_adjust = min(s.width(), s.height())
self.graphics_view.resize_for(width+scrollbar_adjust, height+scrollbar_adjust)
desktop = QCoreApplication.instance().desktop() desktop = QCoreApplication.instance().desktop()
screen_height = desktop.availableGeometry().height() - 25 screen_height = desktop.availableGeometry().height() - 25
height = min(screen_height, height+55) height = min(screen_height, height+hdelta+scrollbar_adjust)
self.resize(self.size().width(), height) self.resize(width+scrollbar_adjust, height)
self.setWindowTitle(self.renderer.lrf.metadata.title + ' - ' + __appname__) self.setWindowTitle(self.renderer.lrf.metadata.title + ' - ' + __appname__)
self.document_title = self.renderer.lrf.metadata.title self.document_title = self.renderer.lrf.metadata.title
if self.opts.profile: if self.opts.profile:
@ -183,6 +189,7 @@ class Main(MainWindow, Ui_MainWindow):
self.document.render(self.renderer.lrf) self.document.render(self.renderer.lrf)
print 'Layout time:', time.time()-start, 'seconds' print 'Layout time:', time.time()-start, 'seconds'
self.renderer.lrf = None self.renderer.lrf = None
self.graphics_view.setScene(self.document) self.graphics_view.setScene(self.document)
self.graphics_view.show() self.graphics_view.show()
self.spin_box.setRange(1, self.document.num_of_pages) self.spin_box.setRange(1, self.document.num_of_pages)

View File

@ -5,8 +5,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>615</width> <width>601</width>
<height>702</height> <height>701</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy" > <property name="sizePolicy" >
@ -38,9 +38,9 @@
<item> <item>
<widget class="QStackedWidget" name="stack" > <widget class="QStackedWidget" name="stack" >
<property name="currentIndex" > <property name="currentIndex" >
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="page" > <widget class="QWidget" name="viewer_page" >
<layout class="QGridLayout" > <layout class="QGridLayout" >
<property name="leftMargin" > <property name="leftMargin" >
<number>0</number> <number>0</number>
@ -162,7 +162,7 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="page_2" > <widget class="QWidget" name="bar_page" >
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<item> <item>
<spacer> <spacer>

View File

@ -12,12 +12,10 @@
## You should have received a copy of the GNU General Public License along ## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc., ## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
from libprs500.gui2.update import CheckForUpdates
from libprs500 import iswindows
from libprs500 import isosx
from libprs500.library.database import LibraryDatabase
import os, sys, textwrap, cStringIO, collections, traceback, shutil import os, sys, textwrap, cStringIO, collections, traceback, shutil
from functools import partial
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \ from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
QSettings, QVariant, QSize, QThread QSettings, QVariant, QSize, QThread
@ -29,13 +27,16 @@ from libprs500 import __version__, __appname__, islinux, sanitize_file_name
from libprs500.ptempfile import PersistentTemporaryFile from libprs500.ptempfile import PersistentTemporaryFile
from libprs500.ebooks.metadata.meta import get_metadata from libprs500.ebooks.metadata.meta import get_metadata
from libprs500.ebooks.lrf.web.convert_from import main as web2lrf from libprs500.ebooks.lrf.web.convert_from import main as web2lrf
from libprs500.ebooks.lrf.any.convert_from import main as any2lrf from libprs500.ebooks.lrf.any.convert_from import main as _any2lrf
from libprs500.devices.errors import FreeSpaceError from libprs500.devices.errors import FreeSpaceError
from libprs500.devices.interface import Device from libprs500.devices.interface import Device
from libprs500.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \ from libprs500.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \
initialize_file_icon_provider, \ initialize_file_icon_provider, \
pixmap_to_data, choose_dir, ORG_NAME, \ pixmap_to_data, choose_dir, ORG_NAME, \
qstring_to_unicode, set_sidebar_directories qstring_to_unicode, set_sidebar_directories
from libprs500 import iswindows, isosx
from libprs500.library.database import LibraryDatabase
from libprs500.gui2.update import CheckForUpdates
from libprs500.gui2.main_window import MainWindow from libprs500.gui2.main_window import MainWindow
from libprs500.gui2.main_ui import Ui_MainWindow from libprs500.gui2.main_ui import Ui_MainWindow
from libprs500.gui2.device import DeviceDetector, DeviceManager from libprs500.gui2.device import DeviceDetector, DeviceManager
@ -55,6 +56,7 @@ from libprs500.ebooks.metadata.meta import set_metadata
from libprs500.ebooks.metadata import MetaInformation from libprs500.ebooks.metadata import MetaInformation
from libprs500.ebooks import BOOK_EXTENSIONS from libprs500.ebooks import BOOK_EXTENSIONS
any2lrf = partial(_any2lrf, gui_mode=True)
class Main(MainWindow, Ui_MainWindow): class Main(MainWindow, Ui_MainWindow):
@ -295,12 +297,14 @@ class Main(MainWindow, Ui_MainWindow):
format = format[1:] if format else None format = format[1:] if format else None
stream = open(book, 'rb') stream = open(book, 'rb')
mi = get_metadata(stream, stream_type=format) mi = get_metadata(stream, stream_type=format)
title = mi.title if mi.title else os.path.splitext(os.path.basename(book))[0] if not mi.title:
mi.title = os.path.splitext(os.path.basename(book))[0]
formats.append(format) formats.append(format)
metadata.append(mi) metadata.append(mi)
names.append(os.path.basename(book)) names.append(os.path.basename(book))
authors = mi.authors if mi.authors else ['Unknown'] if not mi.authors:
infos.append({'title':title, 'authors':', '.join(authors), mi.authors = ['Unknown']
infos.append({'title':mi.title, 'authors':', '.join(mi.authors),
'cover':self.default_thumbnail, 'tags':[]}) 'cover':self.default_thumbnail, 'tags':[]})
if not to_device: if not to_device: