From 79391a5f57bbd60ec3185457245a5a398193e08d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 20 Jul 2007 06:03:01 +0000 Subject: [PATCH] gui2 gets nice error dialogs. --- src/libprs500/devices/interface.py | 3 +++ src/libprs500/devices/prs500/driver.py | 31 +++++++++++------------ src/libprs500/gui2/__init__.py | 34 +++++++++----------------- src/libprs500/gui2/images.qrc | 2 ++ src/libprs500/gui2/main.py | 31 ++++++++++++++--------- 5 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/libprs500/devices/interface.py b/src/libprs500/devices/interface.py index 4d16ff3887..8f267e23e3 100644 --- a/src/libprs500/devices/interface.py +++ b/src/libprs500/devices/interface.py @@ -111,6 +111,9 @@ class Device(object): ''' Upload a list of books to the device. If a file already exists on the device, it should be replaced. + This method should raise a L{FreeSpaceError} if there is not enough + free space on the device. The text of the FreeSpaceError must contain the + word "card" if C{on_card} is True otherwise it must contain the word "memory". @param files: A list of paths and/or file-like objects. @param names: A list of file names that the books should have once uploaded to the device. len(names) == len(files) diff --git a/src/libprs500/devices/prs500/driver.py b/src/libprs500/devices/prs500/driver.py index 958fb0ada4..3b3a8d3389 100755 --- a/src/libprs500/devices/prs500/driver.py +++ b/src/libprs500/devices/prs500/driver.py @@ -830,23 +830,24 @@ class PRS500(Device): def upload_books(self, files, names, on_card=False, end_session=True): card = self.card(end_session=False) prefix = card + '/' if on_card else '/Data/media/books/' - paths, ctimes, sizes = [], [], [] + paths, ctimes = [], [] names = iter(names) - for file in files: - infile = file if hasattr(file, 'read') else open(file, 'rb') - infile.seek(0, 2) - size = infile.tell() - sizes.append(size) + infiles = [file if hasattr(file, 'read') else open(file, 'rb') for file in files] + for f in infiles: f.seek(0, 2) + sizes = [f.tell() for f in infiles] + size = sum(sizes) + space = self.free_space(end_session=False) + mspace = space[0] + cspace = space[1] if space[1] >= space[2] else space[2] + if on_card and size > cspace - 1024*1024: + raise FreeSpaceError("There is insufficient free space "+\ + "on the storage card") + if not on_card and size > mspace - 2*1024*1024: + raise FreeSpaceError("There is insufficient free space " +\ + "in main memory") + + for infile in infiles: infile.seek(0) - space = self.free_space(end_session=False) - mspace = space[0] - cspace = space[1] if space[1] >= space[2] else space[2] - if on_card and size > cspace - 1024*1024: - raise FreeSpaceError("There is insufficient free space "+\ - "on the storage card") - if not on_card and size > mspace - 1024*1024: - raise FreeSpaceError("There is insufficient free space " +\ - "in main memory") name = names.next() paths.append(prefix+name) self.put_file(infile, paths[-1], replace_file=True, end_session=False) diff --git a/src/libprs500/gui2/__init__.py b/src/libprs500/gui2/__init__.py index 2007381ada..4f041b10a7 100644 --- a/src/libprs500/gui2/__init__.py +++ b/src/libprs500/gui2/__init__.py @@ -15,7 +15,7 @@ """ The GUI for libprs500. """ import sys, os, re, StringIO, traceback from PyQt4.QtCore import QVariant, QSettings -from PyQt4.QtGui import QFileDialog +from PyQt4.QtGui import QFileDialog, QMessageBox, QPixmap from libprs500 import __appname__ as APP_TITLE from libprs500 import __author__ NONE = QVariant() #: Null value to return from the data function of item models @@ -25,29 +25,19 @@ error_dialog = None def extension(path): return os.path.splitext(path)[1][1:].lower() -def installErrorHandler(dialog): - ''' Create the error dialog for unhandled exceptions''' - global error_dialog - error_dialog = dialog - error_dialog.resize(600, 400) - error_dialog.setWindowTitle(APP_TITLE + " - Error") - error_dialog.setModal(True) +def warning_dialog(parent, title, msg): + d = QMessageBox(QMessageBox.Warning, 'WARNING: '+title, msg, QMessageBox.Ok, + parent) + d.setIconPixmap(QPixmap(':/images/dialog_warning.svg')) + return d + +def error_dialog(parent, title, msg): + d = QMessageBox(QMessageBox.Critical, 'ERROR: '+title, msg, QMessageBox.Ok, + parent) + d.setIconPixmap(QPixmap(':/images/dialog_error.svg')) + return d -def _Warning(msg, e): - print >> sys.stderr, msg - if e: - traceback.print_exc(e) - -def Error(msg, e): - if error_dialog: - if e: - msg += "
" + traceback.format_exc(e) - msg = re.sub("Traceback", "Traceback", msg) - msg = re.sub(r"\n", "
", msg) - error_dialog.showMessage(msg) - error_dialog.show() - def human_readable(size): """ Convert a size in bytes into a human readable form """ if size < 1024: diff --git a/src/libprs500/gui2/images.qrc b/src/libprs500/gui2/images.qrc index ee1a134661..0be3745b8e 100644 --- a/src/libprs500/gui2/images.qrc +++ b/src/libprs500/gui2/images.qrc @@ -2,6 +2,8 @@ images/book.svg images/clear_left.svg + images/dialog_error.svg + images/dialog_warning.svg images/edit_input.svg images/jobs-animated.mng images/jobs.svg diff --git a/src/libprs500/gui2/main.py b/src/libprs500/gui2/main.py index 06c2acbb56..66139b86b3 100644 --- a/src/libprs500/gui2/main.py +++ b/src/libprs500/gui2/main.py @@ -12,18 +12,18 @@ ## 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 -from libprs500.devices.interface import Device -from libprs500 import __appname__ import os, tempfile, sys from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \ QSettings, QVariant, QSize, QThread, QBuffer, QByteArray -from PyQt4.QtGui import QErrorMessage, QPixmap, QColor, QPainter, QMenu, QIcon +from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon from PyQt4.QtSvg import QSvgRenderer -from libprs500 import __version__ as VERSION +from libprs500 import __version__, __appname__ from libprs500.ebooks.metadata.meta import get_metadata -from libprs500.gui2 import APP_TITLE, installErrorHandler, choose_files +from libprs500.devices.errors import FreeSpaceError +from libprs500.devices.interface import Device +from libprs500.gui2 import APP_TITLE, warning_dialog, choose_files, error_dialog from libprs500.gui2.main_ui import Ui_MainWindow from libprs500.gui2.device import DeviceDetector, DeviceManager from libprs500.gui2.status import StatusBar @@ -60,7 +60,7 @@ class Main(QObject, Ui_MainWindow): self.location_selected) ####################### Vanity ######################## - self.vanity_template = self.vanity.text().arg(VERSION) + self.vanity_template = self.vanity.text().arg(__version__) self.vanity.setText(self.vanity_template.arg(' ')) ####################### Status Bar ##################### @@ -238,7 +238,15 @@ class Main(QObject, Ui_MainWindow): ''' metadata = self.upload_memory.pop(id) if exception: - self.job_exception(id, exception, formatted_traceback) + 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', + '

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

    '%(titles,)) + d.exec_() + else: + self.job_exception(id, exception, formatted_traceback) return self.device_manager.add_books_to_metadata(result, metadata, self.booklists()) @@ -343,15 +351,17 @@ class Main(QObject, Ui_MainWindow): mi = metadata.next() id = ids.next() if f is None: - bad.append(mi) + bad.append(mi['title']) else: good.append(mi) gf.append(f) names.append('%s_%d%s'%(__appname__, id, os.path.splitext(f.name)[1])) self.upload_books(gf, names, good, on_card) - raise Exception, str(bad) - + if bad: + bad = '\n'.join('
  • %s
  • '%(i,) for i in bad) + d = warning_dialog(self.window, 'No suitable formats', 'Could not upload the following books to the device, as no suitable formats were found:
    '%(bad,)) + d.exec_() ############################################################################ @@ -411,7 +421,6 @@ def main(): #return 0 window = QMainWindow() window.setWindowTitle(APP_TITLE) - installErrorHandler(QErrorMessage(window)) QCoreApplication.setOrganizationName("KovidsBrain") QCoreApplication.setApplicationName(APP_TITLE) main = Main(window)