gui2 gets nice error dialogs.

This commit is contained in:
Kovid Goyal 2007-07-20 06:03:01 +00:00
parent 0daf6d3588
commit 79391a5f57
5 changed files with 53 additions and 48 deletions

View File

@ -111,6 +111,9 @@ class Device(object):
''' '''
Upload a list of books to the device. If a file already Upload a list of books to the device. If a file already
exists on the device, it should be replaced. 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 files: A list of paths and/or file-like objects.
@param names: A list of file names that the books should have @param names: A list of file names that the books should have
once uploaded to the device. len(names) == len(files) once uploaded to the device. len(names) == len(files)

View File

@ -830,23 +830,24 @@ class PRS500(Device):
def upload_books(self, files, names, on_card=False, end_session=True): def upload_books(self, files, names, on_card=False, end_session=True):
card = self.card(end_session=False) card = self.card(end_session=False)
prefix = card + '/' if on_card else '/Data/media/books/' prefix = card + '/' if on_card else '/Data/media/books/'
paths, ctimes, sizes = [], [], [] paths, ctimes = [], []
names = iter(names) names = iter(names)
for file in files: infiles = [file if hasattr(file, 'read') else open(file, 'rb') for file in files]
infile = file if hasattr(file, 'read') else open(file, 'rb') for f in infiles: f.seek(0, 2)
infile.seek(0, 2) sizes = [f.tell() for f in infiles]
size = infile.tell() size = sum(sizes)
sizes.append(size) 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) 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() name = names.next()
paths.append(prefix+name) paths.append(prefix+name)
self.put_file(infile, paths[-1], replace_file=True, end_session=False) self.put_file(infile, paths[-1], replace_file=True, end_session=False)

View File

@ -15,7 +15,7 @@
""" The GUI for libprs500. """ """ The GUI for libprs500. """
import sys, os, re, StringIO, traceback import sys, os, re, StringIO, traceback
from PyQt4.QtCore import QVariant, QSettings 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 __appname__ as APP_TITLE
from libprs500 import __author__ from libprs500 import __author__
NONE = QVariant() #: Null value to return from the data function of item models NONE = QVariant() #: Null value to return from the data function of item models
@ -25,28 +25,18 @@ error_dialog = None
def extension(path): def extension(path):
return os.path.splitext(path)[1][1:].lower() return os.path.splitext(path)[1][1:].lower()
def installErrorHandler(dialog): def warning_dialog(parent, title, msg):
''' Create the error dialog for unhandled exceptions''' d = QMessageBox(QMessageBox.Warning, 'WARNING: '+title, msg, QMessageBox.Ok,
global error_dialog parent)
error_dialog = dialog d.setIconPixmap(QPixmap(':/images/dialog_warning.svg'))
error_dialog.resize(600, 400) return d
error_dialog.setWindowTitle(APP_TITLE + " - Error")
error_dialog.setModal(True)
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 += "<br>" + traceback.format_exc(e)
msg = re.sub("Traceback", "<b>Traceback</b>", msg)
msg = re.sub(r"\n", "<br>", msg)
error_dialog.showMessage(msg)
error_dialog.show()
def human_readable(size): def human_readable(size):
""" Convert a size in bytes into a human readable form """ """ Convert a size in bytes into a human readable form """

View File

@ -2,6 +2,8 @@
<qresource prefix="/" > <qresource prefix="/" >
<file>images/book.svg</file> <file>images/book.svg</file>
<file>images/clear_left.svg</file> <file>images/clear_left.svg</file>
<file>images/dialog_error.svg</file>
<file>images/dialog_warning.svg</file>
<file>images/edit_input.svg</file> <file>images/edit_input.svg</file>
<file>images/jobs-animated.mng</file> <file>images/jobs-animated.mng</file>
<file>images/jobs.svg</file> <file>images/jobs.svg</file>

View File

@ -12,18 +12,18 @@
## 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.devices.interface import Device
from libprs500 import __appname__
import os, tempfile, sys import os, tempfile, sys
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \ from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
QSettings, QVariant, QSize, QThread, QBuffer, QByteArray 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 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.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.main_ui import Ui_MainWindow
from libprs500.gui2.device import DeviceDetector, DeviceManager from libprs500.gui2.device import DeviceDetector, DeviceManager
from libprs500.gui2.status import StatusBar from libprs500.gui2.status import StatusBar
@ -60,7 +60,7 @@ class Main(QObject, Ui_MainWindow):
self.location_selected) self.location_selected)
####################### Vanity ######################## ####################### Vanity ########################
self.vanity_template = self.vanity.text().arg(VERSION) self.vanity_template = self.vanity.text().arg(__version__)
self.vanity.setText(self.vanity_template.arg(' ')) self.vanity.setText(self.vanity_template.arg(' '))
####################### Status Bar ##################### ####################### Status Bar #####################
@ -238,7 +238,15 @@ class Main(QObject, Ui_MainWindow):
''' '''
metadata = self.upload_memory.pop(id) metadata = self.upload_memory.pop(id)
if exception: 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(['<li>'+mi['title']+'</li>' for mi in metadata])
d = error_dialog(self.window, 'No space on device',
'<p>Cannot upload books to device there is no more free space available '+where+
'</p><ul>%s</ul>'%(titles,))
d.exec_()
else:
self.job_exception(id, exception, formatted_traceback)
return return
self.device_manager.add_books_to_metadata(result, metadata, self.booklists()) self.device_manager.add_books_to_metadata(result, metadata, self.booklists())
@ -343,15 +351,17 @@ class Main(QObject, Ui_MainWindow):
mi = metadata.next() mi = metadata.next()
id = ids.next() id = ids.next()
if f is None: if f is None:
bad.append(mi) bad.append(mi['title'])
else: else:
good.append(mi) good.append(mi)
gf.append(f) gf.append(f)
names.append('%s_%d%s'%(__appname__, id, os.path.splitext(f.name)[1])) names.append('%s_%d%s'%(__appname__, id, os.path.splitext(f.name)[1]))
self.upload_books(gf, names, good, on_card) self.upload_books(gf, names, good, on_card)
raise Exception, str(bad) if bad:
bad = '\n'.join('<li>%s</li>'%(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:<br><ul>%s</ul>'%(bad,))
d.exec_()
############################################################################ ############################################################################
@ -411,7 +421,6 @@ def main():
#return 0 #return 0
window = QMainWindow() window = QMainWindow()
window.setWindowTitle(APP_TITLE) window.setWindowTitle(APP_TITLE)
installErrorHandler(QErrorMessage(window))
QCoreApplication.setOrganizationName("KovidsBrain") QCoreApplication.setOrganizationName("KovidsBrain")
QCoreApplication.setApplicationName(APP_TITLE) QCoreApplication.setApplicationName(APP_TITLE)
main = Main(window) main = Main(window)