diff --git a/src/libprs500/__init__.py b/src/libprs500/__init__.py index b1df597f98..1af2231930 100644 --- a/src/libprs500/__init__.py +++ b/src/libprs500/__init__.py @@ -13,7 +13,7 @@ ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ''' E-book management software''' -__version__ = "0.4.3" +__version__ = "0.4.4" __docformat__ = "epytext" __author__ = "Kovid Goyal " __appname__ = 'libprs500' diff --git a/src/libprs500/ebooks/lrf/parser.py b/src/libprs500/ebooks/lrf/parser.py index 2ea97d2c3e..8ced8ce5f7 100644 --- a/src/libprs500/ebooks/lrf/parser.py +++ b/src/libprs500/ebooks/lrf/parser.py @@ -32,6 +32,9 @@ class LRFDocument(LRFMetaFile): self.page_trees = [] self.font_map = {} self.image_map = {} + self.keep_parsing = True + + def parse(self): self._parse_objects() self.toc = None self.metadata = LRFDocument.temp() @@ -53,9 +56,13 @@ class LRFDocument(LRFMetaFile): if ord(array.array("i",[1]).tostring()[0])==0: #big-endian obj_array.byteswap() for i in range(self.number_of_objects): + if not self.keep_parsing: + break objid, objoff, objsize = obj_array[i*4:i*4+3] self._parse_object(objid, objoff, objsize) for obj in self.objects.values(): + if not self.keep_parsing: + break if hasattr(obj, 'initialize'): obj.initialize() @@ -155,6 +162,7 @@ def main(args=sys.argv, logger=None): o.write(u'\n') logger.info('Parsing LRF...') d = LRFDocument(open(args[1], 'rb')) + d.parse() logger.info('Creating XML...') o.write(d.to_xml()) logger.info('LRS written to '+opts.out) diff --git a/src/libprs500/gui2/images.qrc b/src/libprs500/gui2/images.qrc index 5e4a84cced..9f7187e088 100644 --- a/src/libprs500/gui2/images.qrc +++ b/src/libprs500/gui2/images.qrc @@ -47,5 +47,6 @@ images/sd.svg images/sync.svg images/trash.svg + images/view.svg diff --git a/src/libprs500/gui2/images/view.svg b/src/libprs500/gui2/images/view.svg new file mode 100644 index 0000000000..7bdbb392dc --- /dev/null +++ b/src/libprs500/gui2/images/view.svg @@ -0,0 +1,2071 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Oxygen team + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libprs500/gui2/lrf_renderer/document.py b/src/libprs500/gui2/lrf_renderer/document.py index 0f806af2bf..fe36fd1c18 100644 --- a/src/libprs500/gui2/lrf_renderer/document.py +++ b/src/libprs500/gui2/lrf_renderer/document.py @@ -108,12 +108,9 @@ class _Canvas(QGraphicsRectItem): canvas.setParentItem(self) canvas.setPos(x, y) canvas.has_content = False - oy = self.current_y - for block, x, y in canvas.items: - self.layout_block(block, x, oy+y) - self.current_y = oy + canvas.max_y - - + canvas.put_objects() + self.current_y += canvas.max_y + def layout_text_block(self, block, x, y): textwidth = block.bs.blockwidth - block.bs.sidemargin if block.max_y == 0 or not block.lines: # Empty block skipping @@ -148,7 +145,11 @@ class _Canvas(QGraphicsRectItem): rl.has_content = False def layout_image_block(self, ib, x, y): - if self.current_y + ib.height > self.max_y-y and self.current_y < 5: + mw, mh = self.max_x - x, self.max_y - y + print self, mw, mh + if ib.width > mw or ib.height > mh: + ib.resize(mw, mh) + if self.current_y + ib.height > self.max_y-y and self.current_y > 5: self.is_full = True else: br = ib.boundingRect() @@ -201,6 +202,10 @@ class Canvas(_Canvas, ContentObject): if item: self.items.append((item, po.x, po.y)) + def put_objects(self): + for block, x, y in self.items: + self.layout_block(block, x, y) + def layout_block(self, block, x, y): block.reset() _Canvas.layout_block(self, block, x, y) diff --git a/src/libprs500/gui2/lrf_renderer/main.py b/src/libprs500/gui2/lrf_renderer/main.py index fc84bad006..158d06ed3a 100644 --- a/src/libprs500/gui2/lrf_renderer/main.py +++ b/src/libprs500/gui2/lrf_renderer/main.py @@ -33,6 +33,7 @@ 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.aborted = False self.lrf = None self.document = None self.exception = None @@ -40,25 +41,36 @@ class RenderWorker(QThread): def run(self): try: self.lrf = LRFDocument(self.stream) + self.lrf.parse() self.stream.close() - self.stream = None + self.stream = None + if self.aborted: + self.lrf = None except Exception, err: + self.lrf, self.stream = None, None self.exception = err self.formatted_traceback = traceback.format_exc() - self.emit(SIGNAL('parsed()')) + + def abort(self): + if self.lrf is not None: + self.aborted = True + self.lrf.keep_parsing = False -class Main(QObject, Ui_MainWindow, MainWindow): - def __init__(self, window, stream, logger, opts): - QObject.__init__(self) +class Main(MainWindow, Ui_MainWindow): + + def __init__(self, stream, logger, opts, parent=None): + MainWindow.__init__(self, parent) Ui_MainWindow.__init__(self) - self.setupUi(window) - self.window = window + self.setupUi(self) + self.setAttribute(Qt.WA_DeleteOnClose) + self.setWindowTitle(__appname__ + ' - LRF Viewer') + self.logger = logger self.file_name = os.path.basename(stream.name) if hasattr(stream, 'name') else '' self.opts = opts self.document = None self.renderer = RenderWorker(self, stream, logger, opts) - QObject.connect(self.renderer, SIGNAL('parsed()'), self.parsed, Qt.QueuedConnection) + QObject.connect(self.renderer, SIGNAL('finished()'), 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) @@ -85,6 +97,9 @@ class Main(QObject, Ui_MainWindow, MainWindow): self.graphics_view.setRenderHint(QPainter.TextAntialiasing, True) self.graphics_view.setRenderHint(QPainter.SmoothPixmapTransform, True) + self.closed = False + + def page_changed(self, num): self.slider.setValue(num) self.spin_box.setValue(num) @@ -98,13 +113,13 @@ class Main(QObject, Ui_MainWindow, MainWindow): try: self.document.search(search) except StopIteration: - error_dialog(self.window, 'No matches found', 'No matches for the search phrase %s were found.'%(search,)).exec_() + error_dialog(self, 'No matches found', 'No matches for the search phrase %s were found.'%(search,)).exec_() - def parsed(self, *args): - if self.renderer.lrf is not None: + def parsed(self): + if not self.renderer.aborted and 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.setWindowTitle(self.renderer.lrf.metadata.title + ' - ' + __appname__) self.document_title = self.renderer.lrf.metadata.title if self.opts.profile: import cProfile @@ -123,7 +138,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): self.spin_box.setSuffix(' of %d'%(self.document.num_of_pages,)) self.spin_box.updateGeometry() self.stack.setCurrentIndex(0) - else: + elif self.renderer.exception is not None: exception = self.renderer.exception print >>sys.stderr, 'Error rendering document' print >>sys.stderr, exception @@ -132,7 +147,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): msg += u'

Failed to render document

' msg += u'

Detailed traceback:

'
             msg += self.renderer.formatted_traceback + '
' - d = ConversionErrorDialog(self.window, 'Error while rendering file', msg) + d = ConversionErrorDialog(self, 'Error while rendering file', msg) d.exec_() def chapter_rendered(self, num): @@ -159,14 +174,22 @@ class Main(QObject, Ui_MainWindow, MainWindow): def back(self, triggered): self.document.back() + + def closeEvent(self, event): + if self.renderer.isRunning(): + self.renderer.abort() + self.renderer.wait() + self.emit(SIGNAL('viewer_closed(PyQt_PyObject)'), self) + event.accept() -def file_renderer(stream, logger, opts): - from PyQt4.Qt import QMainWindow - window = QMainWindow() - window.setAttribute(Qt.WA_DeleteOnClose) - window.setWindowTitle(__appname__ + ' - LRF Viewer') - return Main(window, stream, logger, opts) +def file_renderer(stream, opts, parent=None, logger=None): + if logger is None: + level = logging.DEBUG if opts.verbose else logging.INFO + logger = logging.getLogger('lrfviewer') + setup_cli_handlers(logger, level) + + return Main(stream, logger, opts, parent=parent) def option_parser(): @@ -191,18 +214,14 @@ def main(args=sys.argv, logger=None): if len(args) != 2: parser.print_help() return 1 - if logger is None: - level = logging.DEBUG if opts.verbose else logging.INFO - logger = logging.getLogger('lrf2lrs') - setup_cli_handlers(logger, level) - pid = os.fork() if False and islinux else -1 + pid = os.fork() if islinux else -1 if pid <= 0: app = QApplication(args) QCoreApplication.setOrganizationName(ORG_NAME) QCoreApplication.setApplicationName(APP_UID) - main = file_renderer(open(args[1], 'rb'), logger, opts) + main = file_renderer(open(args[1], 'rb'), opts, logger=logger) sys.excepthook = main.unhandled_exception - main.window.show() + main.show() main.render() return app.exec_() return 0 diff --git a/src/libprs500/gui2/lrf_renderer/text.py b/src/libprs500/gui2/lrf_renderer/text.py index 14f64d2dfb..b191bda3c2 100644 --- a/src/libprs500/gui2/lrf_renderer/text.py +++ b/src/libprs500/gui2/lrf_renderer/text.py @@ -42,6 +42,11 @@ class PixmapItem(QGraphicsPixmapItem): self.height, self.width = ysize, xsize self.setTransformationMode(Qt.SmoothTransformation) self.setShapeMode(QGraphicsPixmapItem.BoundingRectShape) + + def resize(self, width, height): + p = self.pixmap() + self.setPixmap(p.scaled(width, height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)) + self.width, self.height = width, height class Plot(PixmapItem): @@ -213,7 +218,10 @@ class TextBlock(object): def end_link(self): if self.current_line is not None: self.current_line.end_link() - + + def close_valign(self): + if self.current_line is not None: + self.current_line.valign = None def populate(self, tb): self.create_line() @@ -260,10 +268,13 @@ class TextBlock(object): self.end_line() self.create_line() self.current_line.add_plot(plot) - elif i.name == 'Sup': - open_containers.append((('current_style', self.current_style.copy()),)) - elif i.name == 'Sub': - open_containers.append((('current_style', self.current_style.copy()),)) + elif i.name in ['Sup', 'Sub']: + if self.current_line is None: + self.create_line() + self.current_line.valign = i.name + open_containers.append(((self.close_valign, []),)) + elif i.name == 'Space': + self.current_line.add_space(i.attrs['xsize']) elif i.name == 'EmpLine': if i.attrs: open_containers.append((('current_style', self.current_style.copy()),)) @@ -356,6 +367,7 @@ class Line(QGraphicsItem): self.height, self.descent = 0, 0 self.links = collections.deque() self.current_link = None + self.valign = None def start_link(self, refobj, slot): self.current_link = [self.current_width, sys.maxint, refobj, slot] @@ -380,6 +392,8 @@ class Line(QGraphicsItem): processed = False matches = self.__class__.whitespace.finditer(phrase) font = QFont(ts.font) + if self.valign is not None: + font.setPixelSize(font.pixelSize()/1.5) fm = QFontMetrics(font) single_space_width = fm.width(' ') height, descent = fm.height(), fm.descent() @@ -423,7 +437,7 @@ class Line(QGraphicsItem): return phrase_pos, False def commit(self, word, width, height, descent, ts, font): - self.tokens.append(Word(word, width, height, ts, font)) + self.tokens.append(Word(word, width, height, ts, font, self.valign)) self.current_width += width self.height = max(self.height, height) self.descent = max(self.descent, descent) @@ -483,7 +497,6 @@ class Line(QGraphicsItem): x += tok elif isinstance(tok, Word): painter.setFont(tok.font) - p = painter.pen() if tok.highlight: painter.save() painter.setPen(QPen(Qt.NoPen)) @@ -491,8 +504,12 @@ class Line(QGraphicsItem): painter.drawRect(x, 0, tok.width, tok.height) painter.restore() painter.setPen(QPen(tok.text_color)) - painter.drawText(x, y, tok.string) - painter.setPen(p) + if tok.valign is None: + painter.drawText(x, y, tok.string) + elif tok.valign == 'Sub': + painter.drawText(x+1, y+self.descent/1.5, tok.string) + elif tok.valign == 'Sup': + painter.drawText(x+1, y-2.*self.descent, tok.string) x += tok.width else: painter.drawPixmap(x, 0, tok.pixmap()) @@ -546,11 +563,12 @@ class Line(QGraphicsItem): class Word(object): - def __init__(self, string, width, height, ts, font): + def __init__(self, string, width, height, ts, font, valign): self.string, self.width, self.height = QString(string), width, height self.font = font self.text_color = ts.textcolor self.highlight = False + self.valign = valign def main(args=sys.argv): return 0 diff --git a/src/libprs500/gui2/main.py b/src/libprs500/gui2/main.py index 20c92e6fe7..73cc5e118a 100644 --- a/src/libprs500/gui2/main.py +++ b/src/libprs500/gui2/main.py @@ -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, textwrap +import os, sys, textwrap, cStringIO, collections from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \ QSettings, QVariant, QSize, QThread @@ -41,8 +41,10 @@ from libprs500.gui2.dialogs.jobs import JobsDialog from libprs500.gui2.dialogs.conversion_error import ConversionErrorDialog from libprs500.gui2.dialogs.lrf_single import LRFSingleDialog from libprs500.gui2.dialogs.password import PasswordDialog +from libprs500.gui2.lrf_renderer.main import file_renderer +from libprs500.gui2.lrf_renderer.main import option_parser as lrfviewerop -class Main(QObject, Ui_MainWindow, MainWindow): +class Main(MainWindow, Ui_MainWindow): def set_default_thumbnail(self, height): r = QSvgRenderer(':/images/book.svg') @@ -53,24 +55,25 @@ class Main(QObject, Ui_MainWindow, MainWindow): p.end() self.default_thumbnail = (pixmap.width(), pixmap.height(), pixmap_to_data(pixmap)) - def __init__(self, window): - QObject.__init__(self) + def __init__(self, parent=None): + MainWindow.__init__(self, parent) Ui_MainWindow.__init__(self) - self.window = window - self.setupUi(window) + self.setupUi(self) + self.setWindowTitle(__appname__) self.read_settings() self.job_manager = JobManager() - self.jobs_dialog = JobsDialog(self.window, self.job_manager) + self.jobs_dialog = JobsDialog(self, self.job_manager) self.device_manager = None self.upload_memory = {} self.delete_memory = {} self.conversion_jobs = {} self.persistent_files = [] self.default_thumbnail = None - self.device_error_dialog = ConversionErrorDialog(self.window, 'Error communicating with device', ' ') + self.device_error_dialog = ConversionErrorDialog(self, 'Error communicating with device', ' ') self.device_error_dialog.setModal(Qt.NonModal) self.tb_wrapper = textwrap.TextWrapper(width=40) self.device_connected = False + self.viewers = collections.deque() ####################### Location View ######################## QObject.connect(self.location_view, SIGNAL('location_selected(PyQt_PyObject)'), self.location_selected) @@ -83,7 +86,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): ####################### Status Bar ##################### self.status_bar = StatusBar(self.jobs_dialog) - self.window.setStatusBar(self.status_bar) + self.setStatusBar(self.status_bar) QObject.connect(self.job_manager, SIGNAL('job_added(int)'), self.status_bar.job_added) QObject.connect(self.job_manager, SIGNAL('job_done(int)'), self.status_bar.job_done) @@ -105,6 +108,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): QObject.connect(sm.actions()[0], SIGNAL('triggered(bool)'), self.sync_to_main_memory) QObject.connect(sm.actions()[1], SIGNAL('triggered(bool)'), self.sync_to_card) QObject.connect(self.action_save, SIGNAL("triggered(bool)"), self.save_to_disk) + QObject.connect(self.action_view, SIGNAL("triggered(bool)"), self.view_book) self.action_sync.setMenu(sm) self.action_edit.setMenu(md) nm = QMenu() @@ -141,8 +145,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): self.memory_view.connect_dirtied_signal(self.upload_booklists) self.card_view.connect_dirtied_signal(self.upload_booklists) - window.closeEvent = self.close_event - window.show() + self.show() self.stack.setCurrentIndex(0) self.library_view.migrate_database() self.library_view.sortByColumn(3, Qt.DescendingOrder) @@ -254,7 +257,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): ''' Add books from the local filesystem to either the library or the device. ''' - books = choose_files(self.window, 'add books dialog dir', 'Select books', + books = choose_files(self, 'add books dialog dir', 'Select books', filters=[('Books', BOOK_EXTENSIONS)]) if not books: return @@ -312,7 +315,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): if isinstance(exception, FreeSpaceError): where = 'in main memory.' if 'memory' in str(exception) else 'on the storage card.' titles = '\n'.join(['
  • '+mi['title']+'
  • ' for mi in metadata]) - d = error_dialog(self.window, 'No space on device', + d = error_dialog(self, 'No space on device', '

    Cannot upload books to device there is no more free space available '+where+ '

    \n'%(titles,)) d.exec_() @@ -380,12 +383,12 @@ class Main(QObject, Ui_MainWindow, MainWindow): ''' rows = self.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self.window, 'Cannot edit metadata', 'No books selected') + d = error_dialog(self, 'Cannot edit metadata', 'No books selected') d.exec_() return changed = False for row in rows: - if MetadataSingleDialog(self.window, row.row(), + if MetadataSingleDialog(self, row.row(), self.library_view.model().db).changed: changed = True @@ -399,10 +402,10 @@ class Main(QObject, Ui_MainWindow, MainWindow): ''' rows = [r.row() for r in self.library_view.selectionModel().selectedRows()] if not rows or len(rows) == 0: - d = error_dialog(self.window, 'Cannot edit metadata', 'No books selected') + d = error_dialog(self, 'Cannot edit metadata', 'No books selected') d.exec_() return - if MetadataBulkDialog(self.window, rows, self.library_view.model().db).changed: + if MetadataBulkDialog(self, rows, self.library_view.model().db).changed: self.library_view.model().resort(reset=False) self.library_view.model().research() @@ -451,7 +454,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): self.status_bar.showMessage('Sending books to device.', 5000) if bad: bad = '\n'.join('
  • %s
  • '%(i,) for i in bad) - d = warning_dialog(self.window, 'No suitable formats', + d = warning_dialog(self, 'No suitable formats', 'Could not upload the following books to the device, as no suitable formats were found:
    '%(bad,)) d.exec_() @@ -462,10 +465,10 @@ class Main(QObject, Ui_MainWindow, MainWindow): def save_to_disk(self, checked): rows = self.current_view().selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self.window, 'Cannot save to disk', 'No books selected') + d = error_dialog(self, 'Cannot save to disk', 'No books selected') d.exec_() return - dir = choose_dir(self.window, 'save to disk dialog', 'Choose destination directory') + dir = choose_dir(self, 'save to disk dialog', 'Choose destination directory') if not dir: return if self.current_view() == self.library_view: @@ -515,7 +518,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): self.fetch_news('newsweek', 'Newsweek') def fetch_news_nytimes(self, checked): - d = PasswordDialog(self.window, 'nytimes info dialog', + d = PasswordDialog(self, 'nytimes info dialog', '

    Please enter your username and password for nytimes.com
    If you do not have, you can register for free.
    Without a registration, some articles will not be downloaded correctly. Click OK to proceed.') d.exec_() if d.result() == QDialog.Accepted: @@ -526,18 +529,18 @@ class Main(QObject, Ui_MainWindow, MainWindow): ############################### Convert #################################### def convert_bulk(self, checked): - d = error_dialog(self.window, 'Cannot convert', 'Not yet implemented.') + d = error_dialog(self, 'Cannot convert', 'Not yet implemented.') d.exec_() def convert_single(self, checked): rows = self.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self.window, 'Cannot convert', 'No books selected') + d = error_dialog(self, 'Cannot convert', 'No books selected') d.exec_() changed = False for row in [r.row() for r in rows]: - d = LRFSingleDialog(self.window, self.library_view.model().db, row) + d = LRFSingleDialog(self, self.library_view.model().db, row) if d.selected_format: d.exec_() if d.result() == QDialog.Accepted: @@ -573,6 +576,40 @@ class Main(QObject, Ui_MainWindow, MainWindow): data.close() self.status_bar.showMessage(description + ' completed', 2000) + #############################View book###################################### + + def view_book(self, triggered): + rows = self.library_view.selectionModel().selectedRows() + if not rows or len(rows) == 0: + d = error_dialog(self, 'Cannot view', 'No book selected') + d.exec_() + return + + row = rows[0].row() + formats = self.library_view.model().db.formats(row) + title = self.library_view.model().db.title(row) + id = self.library_view.model().db.id(row) + if 'LRF' not in formats.upper(): + d = error_dialog(self, 'Cannot view', '%s is not available in LRF format. Please convert it first.'%(title,)) + d.exec_() + return + + data = cStringIO.StringIO(self.library_view.model().db.format(row, 'LRF')) + parser = lrfviewerop() + opts = parser.parse_args(['lrfviewer'])[0] + + viewer = file_renderer(data, opts) + viewer.libprs500_db_id = id + viewer.show() + viewer.render() + self.viewers.append(viewer) + QObject.connect(viewer, SIGNAL('viewer_closed(PyQt_PyObject)'), self.viewer_closed) + + def viewer_closed(self, viewer): + self.viewers.remove(viewer) + + ############################################################################ + ############################################################################ def location_selected(self, location): ''' @@ -626,13 +663,13 @@ class Main(QObject, Ui_MainWindow, MainWindow): msg += formatted_traceback + '' msg += '

    Log:

    '
             msg += log
    -        ConversionErrorDialog(self.window, 'Conversion Error', msg, show=True)
    +        ConversionErrorDialog(self, 'Conversion Error', msg, show=True)
             
         
         def read_settings(self):
             settings = QSettings()
             settings.beginGroup("Main Window")
    -        self.window.resize(settings.value("size", QVariant(QSize(800, 600))).toSize())
    +        self.resize(settings.value("size", QVariant(QSize(800, 600))).toSize())
             settings.endGroup()
             self.database_path = settings.value("database path", 
                     QVariant(os.path.join(os.path.expanduser('~'),'library1.db'))).toString()
    @@ -640,7 +677,7 @@ class Main(QObject, Ui_MainWindow, MainWindow):
         def write_settings(self):
             settings = QSettings()
             settings.beginGroup("Main Window")
    -        settings.setValue("size", QVariant(self.window.size()))
    +        settings.setValue("size", QVariant(self.size()))
             settings.endGroup()
             settings.beginGroup('Book Views')
             self.library_view.write_settings()
    @@ -648,7 +685,7 @@ class Main(QObject, Ui_MainWindow, MainWindow):
                 self.memory_view.write_settings()
             settings.endGroup()
         
    -    def close_event(self, e):
    +    def closeEvent(self, e):
             msg = 'There are active jobs. Are you sure you want to quit?'
             if self.job_manager.has_device_jobs():
                 msg = '

    '+__appname__ + ' is communicating with the device!
    '+\ @@ -656,7 +693,7 @@ class Main(QObject, Ui_MainWindow, MainWindow): 'Are you sure you want to quit?' if self.job_manager.has_jobs(): d = QMessageBox(QMessageBox.Warning, 'WARNING: Active jobs', msg, - QMessageBox.Yes|QMessageBox.No, self.window) + QMessageBox.Yes|QMessageBox.No, self) d.setIconPixmap(QPixmap(':/images/dialog_warning.svg')) d.setDefaultButton(QMessageBox.No) if d.exec_() != QMessageBox.Yes: @@ -669,18 +706,15 @@ class Main(QObject, Ui_MainWindow, MainWindow): def main(args=sys.argv): - from PyQt4.Qt import QApplication, QMainWindow + from PyQt4.Qt import QApplication pid = os.fork() if islinux else -1 if pid <= 0: app = QApplication(args) - window = QMainWindow() - window.setWindowTitle(__appname__) QCoreApplication.setOrganizationName(ORG_NAME) QCoreApplication.setApplicationName(APP_UID) initialize_file_icon_provider() - main = Main(window) - sys.excepthook = main.unhandled_exception - QObject.connect(app, SIGNAL('lastWindowClosed()'), app.quit) + main = Main() + sys.excepthook = main.unhandled_exception return app.exec_() return 0 diff --git a/src/libprs500/gui2/main.ui b/src/libprs500/gui2/main.ui index 484ad9dec6..14eaf6873e 100644 --- a/src/libprs500/gui2/main.ui +++ b/src/libprs500/gui2/main.ui @@ -6,7 +6,7 @@ 0 0 - 787 + 865 822 @@ -316,8 +316,8 @@ - 64 - 64 + 48 + 48 @@ -338,6 +338,7 @@ + @@ -421,6 +422,14 @@ Convert E-books + + + :/images/view.svg + + + View + + diff --git a/src/libprs500/gui2/main_window.py b/src/libprs500/gui2/main_window.py index e5d7374113..89e436f251 100644 --- a/src/libprs500/gui2/main_window.py +++ b/src/libprs500/gui2/main_window.py @@ -15,9 +15,13 @@ import StringIO, traceback, sys +from PyQt4.QtGui import QMainWindow from libprs500.gui2.dialogs.conversion_error import ConversionErrorDialog -class MainWindow(object): +class MainWindow(QMainWindow): + + def __init__(self, parent=None): + QMainWindow.__init__(self, parent) def unhandled_exception(self, type, value, tb): sio = StringIO.StringIO() @@ -26,5 +30,5 @@ class MainWindow(object): print >>sys.stderr, fe msg = '

    ' + unicode(str(value), 'utf8', 'replace') + '

    ' msg += '

    Detailed traceback:

    '+fe+'
    ' - d = ConversionErrorDialog(self.window, 'ERROR: Unhandled exception', msg) + d = ConversionErrorDialog(self, 'ERROR: Unhandled exception', msg) d.exec_() \ No newline at end of file