LRF viewer works on a few test files

This commit is contained in:
Kovid Goyal 2007-09-22 18:12:11 +00:00
parent eef94d5644
commit 64ed20a65d
21 changed files with 988 additions and 245 deletions

View File

@ -813,9 +813,9 @@ class HTMLConverter(object):
height=height))
left = int(floor((pwidth - width)/2.))
self.current_page.contents[-1].put_object(
ImageBlock(self.images[path], xsize=pwidth,
ysize=pheight, x1=pwidth, y1=pheight,
blockwidth=pwidth, blockheight=pheight),
ImageBlock(self.images[path], xsize=width,
ysize=height, x1=width, y1=height,
blockwidth=width, blockheight=height),
left, 0)
def process_page_breaks(self, tag, tagname, tag_css):

View File

@ -93,8 +93,8 @@ class LRFDocument(LRFMetaFile):
bookinfo += u'<FreeText reading="">%s</FreeText>\n</BookInfo>\n<DocInfo>\n'%(self.metadata.free_text,)
th = self.doc_info.thumbnail
if th:
bookinfo += u'<CThumbnail file="%s" />\n'%(self.metadata.title+'_thumbnail.'+self.doc_info.thumbail_extension(),)
open(self.metadata.title+'_thumbnail.'+self.doc_info.thumbail_extension(), 'wb').write(th)
bookinfo += u'<CThumbnail file="%s" />\n'%(self.metadata.title+'_thumbnail.'+self.doc_info.thumbnail_extension,)
open(self.metadata.title+'_thumbnail.'+self.doc_info.thumbnail_extension, 'wb').write(th)
bookinfo += u'<Language reading="">%s</Language>\n'%(self.doc_info.language,)
bookinfo += u'<Creator reading="">%s</Creator>\n'%(self.doc_info.creator,)
bookinfo += u'<Producer reading="">%s</Producer>\n'%(self.doc_info.producer,)

View File

@ -4,7 +4,8 @@ UI = main_ui.py dialogs/metadata_single_ui.py dialogs/metadata_bulk_ui.py dialog
RC = images_rc.pyc
%_ui.py : %.ui
pyuic4 $< | sed "s/import images_rc/from libprs500.gui2 import images_rc/" > $@
pyuic4 $< | sed "s/import images_rc/from libprs500.gui2 import images_rc/" | \
sed "s/from library import/from libprs500.gui2.library import/"> $@
%_rc.pyc : %.qrc %
pyrcc4 $< > $*_rc.py

View File

@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/" >
<file>images/back.svg</file>
<file>images/book.svg</file>
<file>images/chapters.svg</file>
<file>images/clear_left.svg</file>
@ -9,6 +10,7 @@
<file>images/dialog_warning.svg</file>
<file>images/document_open.svg</file>
<file>images/edit_input.svg</file>
<file>images/forward.svg</file>
<file>images/jobs-animated.mng</file>
<file>images/jobs.svg</file>
<file alias="library" >images/library.png</file>
@ -36,8 +38,10 @@
<file>images/news/bbc.png</file>
<file>images/news/newsweek.png</file>
<file>images/news/nytimes.png</file>
<file>images/next.svg</file>
<file>images/page.svg</file>
<file>images/plus.svg</file>
<file>images/previous.svg</file>
<file>images/reader.svg</file>
<file>images/save.svg</file>
<file>images/sd.svg</file>

File diff suppressed because it is too large Load Diff

View File

@ -14,19 +14,40 @@
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
''''''
import sys, logging, os
import sys, logging, os, traceback
from PyQt4.Qt import QApplication, QCoreApplication
from PyQt4.QtCore import Qt, QObject
from PyQt4.QtGui import QApplication, QKeySequence, QPainter
from PyQt4.QtCore import Qt, QObject, SIGNAL, QCoreApplication, QThread
from libprs500 import __appname__, __version__, __author__, setup_cli_handlers, islinux
from libprs500.ebooks.lrf.parser import LRFDocument
from libprs500.gui2 import ORG_NAME, APP_UID
from libprs500.gui2.dialogs.conversion_error import ConversionErrorDialog
from libprs500.gui2.lrf_renderer.main_ui import Ui_MainWindow
from libprs500.gui2.main_window import MainWindow
from libprs500.gui2.lrf_renderer.document import Document
class Main(QObject, Ui_MainWindow):
class RenderWorker(QThread):
def __init__(self, parent, lrf_stream, logger, opts):
QThread.__init__(self, parent)
self.stream, self.logger, self.opts = lrf_stream, logger, opts
self.lrf = None
self.document = None
self.exception = None
def run(self):
try:
self.lrf = LRFDocument(self.stream)
self.stream.close()
self.stream = None
except Exception, err:
self.exception = err
self.formatted_traceback = traceback.format_exc()
self.emit(SIGNAL('parsed()'))
class Main(QObject, Ui_MainWindow, MainWindow):
def __init__(self, window, stream, logger, opts):
QObject.__init__(self)
Ui_MainWindow.__init__(self)
@ -34,28 +55,95 @@ class Main(QObject, Ui_MainWindow):
self.window = window
self.logger = logger
self.file_name = os.path.basename(stream.name) if hasattr(stream, 'name') else ''
self.stream = stream
self.opts = opts
self.document = None
self.renderer = RenderWorker(self, stream, logger, opts)
QObject.connect(self.renderer, SIGNAL('parsed()'), self.parsed, Qt.QueuedConnection)
self.document = Document(self.logger, self.opts)
QObject.connect(self.document, SIGNAL('chapter_rendered(int)'), self.chapter_rendered)
QObject.connect(self.document, SIGNAL('page_changed(PyQt_PyObject)'), self.page_changed)
self.search.help_text = 'Search'
self.search.clear_to_help()
self.action_next_page.setShortcuts(QKeySequence.MoveToNextPage)
self.action_previous_page.setShortcuts(QKeySequence.MoveToPreviousPage)
QObject.connect(self.action_next_page, SIGNAL('triggered(bool)'), self.next)
QObject.connect(self.action_previous_page, SIGNAL('triggered(bool)'), self.previous)
QObject.connect(self.action_back, SIGNAL('triggered(bool)'), self.back)
QObject.connect(self.action_forward, SIGNAL('triggered(bool)'), self.forward)
QObject.connect(self.spin_box, SIGNAL('valueChanged(int)'), self.go_to_page)
QObject.connect(self.slider, SIGNAL('valueChanged(int)'), self.go_to_page)
self.next_button.setDefaultAction(self.action_next_page)
self.previous_button.setDefaultAction(self.action_previous_page)
self.back_button.setDefaultAction(self.action_back)
self.forward_button.setDefaultAction(self.action_forward)
self.graphics_view.setRenderHint(QPainter.Antialiasing, True)
self.graphics_view.setRenderHint(QPainter.TextAntialiasing, True)
self.graphics_view.setRenderHint(QPainter.SmoothPixmapTransform, True)
def page_changed(self, num):
self.slider.setValue(num)
self.spin_box.setValue(num)
def render(self):
self.window.show()
self.statusbar.showMessage('Parsing LRF file '+self.file_name)
QCoreApplication.instance().processEvents()
self.lrf = LRFDocument(self.stream)
self.stream.close()
self.stream = None
self.graphics_view.resize(self.lrf.device_info.width+15, self.lrf.device_info.height)
self.window.setWindowTitle(self.lrf.metadata.title + ' - ' + __appname__)
self.statusbar.showMessage('Building graphical representation')
QCoreApplication.instance().processEvents()
self.stack.setCurrentIndex(1)
self.renderer.start()
def parsed(self, *args):
if self.renderer.lrf is not None:
self.graphics_view.setMinimumSize(self.renderer.lrf.device_info.width+5,
self.renderer.lrf.device_info.height)
self.window.setWindowTitle(self.renderer.lrf.metadata.title + ' - ' + __appname__)
self.document_title = self.renderer.lrf.metadata.title
self.document.render(self.renderer.lrf)
self.renderer.lrf = None
self.graphics_view.setScene(self.document)
self.graphics_view.show()
self.spin_box.setRange(1, self.document.num_of_pages)
self.slider.setRange(1, self.document.num_of_pages)
self.spin_box.setSuffix(' of %d'%(self.document.num_of_pages,))
self.spin_box.updateGeometry()
self.stack.setCurrentIndex(0)
else:
exception = self.renderer.exception
print >>sys.stderr, 'Error rendering document'
print >>sys.stderr, exception
print >>sys.stderr, self.renderer.formatted_traceback
msg = u'<p><b>%s</b>: '%(exception.__class__.__name__,) + unicode(str(exception), 'utf8', 'replace') + u'</p>'
msg += u'<p>Failed to render document</p>'
msg += u'<p>Detailed <b>traceback</b>:<pre>'
msg += self.renderer.formatted_traceback + '</pre>'
d = ConversionErrorDialog(self.window, 'Error while rendering file', msg)
d.exec_()
def chapter_rendered(self, num):
if num > 0:
self.progress_bar.setMinimum(0)
self.progress_bar.setMaximum(num)
self.progress_bar.setValue(0)
self.progress_label.setText('Rendering '+ self.document_title)
else:
self.progress_bar.setValue(self.progress_bar.value()+1)
QCoreApplication.processEvents()
def next(self, triggered):
self.document.next()
def previous(self, triggered):
self.document.previous()
self.document = Document(self.lrf, self.logger, self.opts)
self.graphics_view.setScene(self.document)
self.graphics_view.show()
self.statusbar.clearMessage()
QCoreApplication.instance().processEvents()
self.document.next()
def go_to_page(self, num):
self.document.show_page(num)
def forward(self, triggered):
self.document.forward()
def back(self, triggered):
self.document.back()
def file_renderer(stream, logger, opts):
from PyQt4.Qt import QMainWindow
@ -93,9 +181,13 @@ def main(args=sys.argv, logger=None):
QCoreApplication.setOrganizationName(ORG_NAME)
QCoreApplication.setApplicationName(APP_UID)
main = file_renderer(open(args[1], 'rb'), logger, opts)
sys.excepthook = main.unhandled_exception
main.window.show()
main.render()
return app.exec_()
return 0
if __name__ == '__main__':
sys.exit(main())
sys.exit(main())

View File

@ -5,46 +5,254 @@
<rect>
<x>0</x>
<y>0</y>
<width>858</width>
<height>854</height>
<width>614</width>
<height>832</height>
</rect>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle" >
<string>MainWindow</string>
<string>LRF Viewer</string>
</property>
<widget class="QWidget" name="centralwidget" >
<widget class="QGraphicsView" name="graphics_view" >
<property name="geometry" >
<rect>
<x>0</x>
<y>10</y>
<width>281</width>
<height>321</height>
</rect>
<property name="windowIcon" >
<iconset resource="../images.qrc" >:/library</iconset>
</property>
<widget class="QWidget" name="central_widget" >
<layout class="QVBoxLayout" >
<property name="leftMargin" >
<number>0</number>
</property>
<property name="mouseTracking" >
<bool>true</bool>
<property name="topMargin" >
<number>0</number>
</property>
</widget>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QStackedWidget" name="stack" >
<property name="currentIndex" >
<number>1</number>
</property>
<widget class="QWidget" name="page" >
<layout class="QGridLayout" >
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item row="0" column="0" >
<widget class="QGraphicsView" name="graphics_view" >
<property name="mouseTracking" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QFrame" name="frame" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" >
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="back_button" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="forward_button" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slider" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="previous_button" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spin_box" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="next_button" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="SearchBox" name="search" />
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2" >
<layout class="QVBoxLayout" >
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame_2" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QProgressBar" name="progress_bar" >
<property name="maximum" >
<number>0</number>
</property>
<property name="value" >
<number>-1</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="progress_label" >
<property name="font" >
<font>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text" >
<string>Parsing LRF file</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>858</width>
<height>29</height>
</rect>
<action name="action_next_page" >
<property name="icon" >
<iconset resource="../images.qrc" >:/images/next.svg</iconset>
</property>
</widget>
<widget class="QStatusBar" name="statusbar" />
<property name="text" >
<string>Next Page</string>
</property>
</action>
<action name="action_previous_page" >
<property name="icon" >
<iconset resource="../images.qrc" >:/images/previous.svg</iconset>
</property>
<property name="text" >
<string>Previous Page</string>
</property>
</action>
<action name="action_back" >
<property name="icon" >
<iconset resource="../images.qrc" >:/images/back.svg</iconset>
</property>
<property name="text" >
<string>Back</string>
</property>
</action>
<action name="action_forward" >
<property name="icon" >
<iconset resource="../images.qrc" >:/images/forward.svg</iconset>
</property>
<property name="text" >
<string>Forward</string>
</property>
</action>
</widget>
<resources/>
<customwidgets>
<customwidget>
<class>SearchBox</class>
<extends>QLineEdit</extends>
<header>library.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../images.qrc" />
</resources>
<connections/>
</ui>

View File

@ -12,7 +12,7 @@
## 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.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
import os, sys, traceback, StringIO, textwrap
import os, sys, textwrap
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
QSettings, QVariant, QSize, QThread
@ -30,6 +30,7 @@ from libprs500.devices.interface import Device
from libprs500.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \
initialize_file_icon_provider, BOOK_EXTENSIONS, \
pixmap_to_data, choose_dir, ORG_NAME
from libprs500.gui2.main_window import MainWindow
from libprs500.gui2.main_ui import Ui_MainWindow
from libprs500.gui2.device import DeviceDetector, DeviceManager
from libprs500.gui2.status import StatusBar
@ -41,7 +42,7 @@ from libprs500.gui2.dialogs.conversion_error import ConversionErrorDialog
from libprs500.gui2.dialogs.lrf_single import LRFSingleDialog
from libprs500.gui2.dialogs.password import PasswordDialog
class Main(QObject, Ui_MainWindow):
class Main(QObject, Ui_MainWindow, MainWindow):
def set_default_thumbnail(self, height):
r = QSvgRenderer(':/images/book.svg')
@ -665,15 +666,7 @@ class Main(QObject, Ui_MainWindow):
e.accept()
def unhandled_exception(self, type, value, tb):
sio = StringIO.StringIO()
traceback.print_exception(type, value, tb, file=sio)
fe = sio.getvalue()
print >>sys.stderr, fe
msg = '<p><b>' + unicode(str(value), 'utf8', 'replace') + '</b></p>'
msg += '<p>Detailed <b>traceback</b>:<pre>'+fe+'</pre>'
d = ConversionErrorDialog(self.window, 'ERROR: Unhandled exception', msg)
d.exec_()
def main(args=sys.argv):
from PyQt4.Qt import QApplication, QMainWindow

View File

@ -0,0 +1,30 @@
## Copyright (C) 2007 Kovid Goyal kovid@kovidgoyal.net
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## 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.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import StringIO, traceback, sys
from libprs500.gui2.dialogs.conversion_error import ConversionErrorDialog
class MainWindow(object):
def unhandled_exception(self, type, value, tb):
sio = StringIO.StringIO()
traceback.print_exception(type, value, tb, file=sio)
fe = sio.getvalue()
print >>sys.stderr, fe
msg = '<p><b>' + unicode(str(value), 'utf8', 'replace') + '</b></p>'
msg += '<p>Detailed <b>traceback</b>:<pre>'+fe+'</pre>'
d = ConversionErrorDialog(self.window, 'ERROR: Unhandled exception', msg)
d.exec_()