diff --git a/src/calibre/gui2/dialogs/message_box.py b/src/calibre/gui2/dialogs/message_box.py index a107bf985b..b9e11c9745 100644 --- a/src/calibre/gui2/dialogs/message_box.py +++ b/src/calibre/gui2/dialogs/message_box.py @@ -9,7 +9,7 @@ import sys from PyQt4.Qt import (QDialog, QIcon, QApplication, QSize, QKeySequence, QAction, Qt, QTextBrowser, QDialogButtonBox, QVBoxLayout, QGridLayout, - QLabel, QPlainTextEdit, QTextDocument) + QLabel, QPlainTextEdit, QTextDocument, QCheckBox, pyqtSignal) from calibre.constants import __version__, isfrozen from calibre.gui2.dialogs.message_box_ui import Ui_Dialog @@ -270,12 +270,14 @@ class ErrorNotification(MessageBox): # {{{ class JobError(QDialog): # {{{ WIDTH = 600 + do_pop = pyqtSignal() def __init__(self, gui): QDialog.__init__(self, gui) self.setAttribute(Qt.WA_DeleteOnClose, False) self.gui = gui self.queue = [] + self.do_pop.connect(self.pop, type=Qt.QueuedConnection) self._layout = l = QGridLayout() self.setLayout(l) @@ -285,6 +287,7 @@ class JobError(QDialog): # {{{ self.icon_label.setPixmap(self.icon.pixmap(128, 128)) self.icon_label.setMaximumSize(QSize(128, 128)) self.msg_label = QLabel('

 ') + self.msg_label.setStyleSheet('QLabel { margin-top: 1ex; }') self.msg_label.setWordWrap(True) self.msg_label.setTextFormat(Qt.RichText) self.det_msg = QPlainTextEdit(self) @@ -302,17 +305,25 @@ class JobError(QDialog): # {{{ self.det_msg_toggle.clicked.connect(self.toggle_det_msg) self.det_msg_toggle.setToolTip( _('Show detailed information about this error')) + self.suppress = QCheckBox(self) + self.suppress.setVisible(False) l.addWidget(self.icon_label, 0, 0, 1, 1) - l.addWidget(self.msg_label, 0, 1, 1, 1, Qt.AlignLeft|Qt.AlignTop) - l.addWidget(self.det_msg, 1, 0, 1, 2) - - l.addWidget(self.bb, 2, 0, 1, 2, Qt.AlignRight|Qt.AlignBottom) + l.addWidget(self.msg_label, 0, 1, 1, 1, Qt.AlignTop) + l.addWidget(self.det_msg, 1, 0, 1, 2) + l.addWidget(self.suppress, 2, 0, 1, 2, Qt.AlignLeft|Qt.AlignBottom) + l.addWidget(self.bb, 3, 0, 1, 2, Qt.AlignRight|Qt.AlignBottom) + l.setColumnStretch(1, 100) self.setModal(False) self.base_height = max(200, self.sizeHint().height() + 20) self.do_resize() + def update_suppress_state(self): + self.suppress.setText(_( + 'Hide the remaining %d error messages'%len(self.queue))) + self.suppress.setVisible(len(self.queue) > 3) + def copy_to_clipboard(self, *args): d = QTextDocument() d.setHtml(self.msg_label.text()) @@ -342,6 +353,33 @@ class JobError(QDialog): # {{{ self.bb.button(self.bb.Close).setFocus(Qt.OtherFocusReason) return ret + def show_error(self, title, msg, det_msg=u''): + self.queue.append((title, msg, det_msg)) + self.update_suppress_state() + self.pop() + + def pop(self): + if not self.queue or self.isVisible(): return + title, msg, det_msg = self.queue.pop(0) + self.setWindowTitle(title) + self.msg_label.setText(msg) + self.det_msg.setPlainText(det_msg) + self.det_msg.setVisible(False) + self.det_msg_toggle.setText(self.show_det_msg) + self.det_msg_toggle.setVisible(True) + self.suppress.setChecked(False) + self.update_suppress_state() + if not det_msg: + self.det_msg_toggle.setVisible(False) + self.do_resize() + self.show() + + def done(self, r): + if self.suppress.isChecked(): + self.queue = [] + self.do_pop.emit() + return QDialog.done(self, r) + # }}} if __name__ == '__main__': @@ -349,7 +387,7 @@ if __name__ == '__main__': from calibre.gui2.preferences import init_gui gui = init_gui() d = JobError(gui) - d.show() + d.show_error('test title', 'some long meaningless test message') app.exec_() gui.shutdown() diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 3490c63215..f07fb0d211 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -44,6 +44,7 @@ from calibre.gui2.keyboard import Manager from calibre.gui2.auto_add import AutoAdder from calibre.library.sqlite import sqlite, DatabaseException from calibre.gui2.proceed import ProceedQuestion +from calibre.gui2.dialogs.message_box import JobError class Listener(Thread): # {{{ @@ -111,6 +112,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ self.proceed_requested.connect(self.do_proceed, type=Qt.QueuedConnection) self.proceed_question = ProceedQuestion(self) + self.job_error_dialog = JobError(self) self.keyboard = Manager(self) _gui = self self.opts = opts @@ -690,12 +692,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ except: pass if not minz: - d = error_dialog(self, dialog_title, + self.job_error_dialog.show_error(dialog_title, _('Failed')+': '+unicode(job.description), det_msg=job.details) - d.setModal(False) - d.show() - self._modeless_dialogs.append(d) def read_settings(self): geometry = config['main_window_geometry']