class BusyWidget(QWidget): # {{{ def __init__(self, parent): QWidget.__init__(self, parent) l = QVBoxLayout() self.setLayout(l) l.addStretch(10) self.pi = ProgressIndicator(self, 128) l.addWidget(self.pi, alignment=Qt.AlignmentFlag.AlignHCenter) self.dummy = QLabel('<h2>\xa0') l.addSpacing(10) l.addWidget(self.dummy, alignment=Qt.AlignmentFlag.AlignHCenter) l.addStretch(10) self.text = _('Calculating differences, please wait...') def paintEvent(self, ev): br = ev.region().boundingRect() QWidget.paintEvent(self, ev) p = QPainter(self) p.setClipRect(br) f = p.font() f.setBold(True) f.setPointSize(20) p.setFont(f) p.setPen(Qt.PenStyle.SolidLine) r = QRect(0, self.dummy.geometry().top() + 10, self.geometry().width(), 150) p.drawText(r, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop | Qt.TextFlag.TextSingleLine, self.text) p.end()
class BlockingJob(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) l = QVBoxLayout() self.setLayout(l) l.addStretch(10) self.pi = ProgressIndicator(self, 128) l.addWidget(self.pi, alignment=Qt.AlignmentFlag.AlignHCenter) self.dummy = QLabel('<h2>\xa0') l.addSpacing(10) l.addWidget(self.dummy, alignment=Qt.AlignmentFlag.AlignHCenter) l.addStretch(10) self.setVisible(False) self.text = '' self.setFocusPolicy(Qt.FocusPolicy.NoFocus) def start(self): self.setGeometry(0, 0, self.parent().width(), self.parent().height()) self.setVisible(True) # Prevent any actions from being triggered by key presses self.parent().setEnabled(False) self.raise_() self.setFocus(Qt.FocusReason.OtherFocusReason) self.pi.startAnimation() QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) def stop(self): QApplication.restoreOverrideCursor() self.pi.stopAnimation() self.setVisible(False) self.parent().setEnabled(True) # The following line is needed on OS X, because of this bug: # https://bugreports.qt-project.org/browse/QTBUG-34371 it causes # keyboard events to no longer work self.parent().setFocus(Qt.FocusReason.OtherFocusReason) def job_done(self, callback, job): del job.callback self.stop() callback(job) def paintEvent(self, ev): br = ev.region().boundingRect() p = QPainter(self) p.setOpacity(0.2) p.fillRect(br, QBrush(self.palette().text())) p.end() QWidget.paintEvent(self, ev) p = QPainter(self) p.setClipRect(br) f = p.font() f.setBold(True) f.setPointSize(20) p.setFont(f) p.setPen(Qt.PenStyle.SolidLine) r = QRect(0, self.dummy.geometry().top() + 10, self.geometry().width(), 150) p.drawText( r, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop | Qt.TextFlag.TextSingleLine, self.text) p.end() def set_msg(self, text): self.text = text def __call__(self, name, user_text, callback, function, *args, **kwargs): ' Run a job that blocks the GUI providing some feedback to the user ' self.set_msg(user_text) job = LongJob(name, user_text, Dispatcher(partial(self.job_done, callback)), function, *args, **kwargs) job.start() self.start()