diff --git a/photobooth/gui/PyQt5Gui.py b/photobooth/gui/PyQt5Gui.py index 750789c..65edd01 100644 --- a/photobooth/gui/PyQt5Gui.py +++ b/photobooth/gui/PyQt5Gui.py @@ -120,7 +120,10 @@ class PyQt5Gui(Gui): QtCore.QTimer.singleShot(cfg.getInt('Photobooth', 'greeter_time') * 1000, self.sendAck) elif isinstance(state, CountdownState): - self._p.setCentralWidget(PyQt5CountdownMessage(cfg.getInt('Photobooth', 'countdown_time'), self.sendAck)) + # self._p.setCentralWidget(PyQt5CountdownMessage(cfg.getInt('Photobooth', 'countdown_time'), self.sendAck)) + countdown_time = cfg.getInt('Photobooth', 'countdown_time') + self._p.setCentralWidget(Frames.CountdownMessage(countdown_time, + self.sendAck)) elif isinstance(state, PreviewState): self._p.centralWidget().picture = ImageQt.ImageQt(state.picture) @@ -313,102 +316,3 @@ class PyQt5MainWindow(QtWidgets.QMainWindow): def keyPressEvent(self, event): self.handleKeypressEvent(event) - - - -class PyQt5CountdownMessage(QtWidgets.QFrame): - - def __init__(self, time, action): - - super().__init__() - - self._step_size = 50 - self._counter = time * (1000 // self._step_size) - self._action = action - self._picture = None - - self.initFrame() - self.initProgressBar(time) - - - def initFrame(self): - - self.setStyleSheet('background-color: black; color: white;') - - - def initProgressBar(self, time): - - self._bar = QRoundProgressBar() - self._bar.setBarStyle(QRoundProgressBar.StyleLine) - self._bar.setFixedSize(200, 200) - - self._bar.setDataPenWidth(7) - self._bar.setOutlinePenWidth(10) - - self._bar.setDecimals(0) - self._bar.setFormat('%v') - - self._bar.setRange(0, time) - self._bar.setValue(time) - - - def updateProgressBar(self): - - self._bar.setValue(self._counter / (1000 // self._step_size)) - - - @property - def counter(self): - - return self._counter - - - @property - def picture(self): - - return self._picture - - - @picture.setter - def picture(self, pic): - - if not isinstance(pic, QtGui.QImage): - raise ValueError('picture must be a QtGui.QImage') - - self._picture = pic - - - def paintEvent(self, event): - - painter = QtGui.QPainter(self) - - if self._picture != None: - pix = QtGui.QPixmap.fromImage(self._picture) - pix = pix.scaled(self.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation) - origin = ( (self.width() - pix.width()) // 2, - (self.height() - pix.height()) // 2 ) - painter.drawPixmap(QtCore.QPoint(*origin), pix) - - painter.end() - - offset = ( (self.width() - self._bar.width()) // 2, - (self.height() - self._bar.height()) // 2 ) - self._bar.render(self, QtCore.QPoint(*offset), self._bar.visibleRegion(), QtWidgets.QWidget.DrawChildren) - - - def showEvent(self, event): - - self._timer = self.startTimer(self._step_size) - - - def timerEvent(self, event): - - self._counter -= 1 - - if self._counter == 0: - self.killTimer(self._timer) - self._action() - else: - self.updateProgressBar() - self.update() - diff --git a/photobooth/gui/Qt5Gui/Frames.py b/photobooth/gui/Qt5Gui/Frames.py index 1451932..38c1394 100644 --- a/photobooth/gui/Qt5Gui/Frames.py +++ b/photobooth/gui/Qt5Gui/Frames.py @@ -13,6 +13,8 @@ from .. import modules from ... import camera from ... import printer +from . import Widgets + class Start(QtWidgets.QFrame): @@ -222,6 +224,88 @@ class WaitMessage(QtWidgets.QFrame): painter.end() +class CountdownMessage(QtWidgets.QFrame): + + def __init__(self, time, action): + + super().__init__() + + self._step_size = 50 + self._value = time * (1000 // self._step_size) + self._action = action + self._picture = None + + self._initProgressBar(time) + + def _initProgressBar(self, time): + + self._bar = Widgets.RoundProgressBar(0, time, time) + self._bar.setFixedSize(200, 200) + + def _updateProgressBar(self): + + self._bar.value = self._value / (1000 // self._step_size) + + @property + def value(self): + + return self._value + + @value.setter + def value(self, value): + + self._value = value + + @property + def picture(self): + + return self._picture + + @picture.setter + def picture(self, picture): + + if not isinstance(picture, QtGui.QImage): + raise ValueError('picture must be a QtGui.QImage') + + self._picture = picture + + def paintEvent(self, event): + + # background image + if self.picture is not None: + painter = QtGui.QPainter(self) + + pix = QtGui.QPixmap.fromImage(self.picture) + pix = pix.scaled(self.size(), QtCore.Qt.KeepAspectRatio, + QtCore.Qt.FastTransformation) + origin = ((self.width() - pix.width()) // 2, + (self.height() - pix.height()) // 2) + painter.drawPixmap(QtCore.QPoint(*origin), pix) + + painter.end() + + offset = ((self.width() - self._bar.width()) // 2, + (self.height() - self._bar.height()) // 2) + self._bar.render(self, QtCore.QPoint(*offset), + self._bar.visibleRegion(), + QtWidgets.QWidget.DrawChildren) + + def showEvent(self, event): + + self._timer = self.startTimer(self._step_size) + + def timerEvent(self, event): + + self.value -= 1 + + if self.value == 0: + self.killTimer(self._timer) + self._action() + else: + self._updateProgressBar() + self.update() + + class Settings(QtWidgets.QFrame): def __init__(self, config, reload_action, cancel_action, restart_action): diff --git a/photobooth/gui/Qt5Gui/Widgets.py b/photobooth/gui/Qt5Gui/Widgets.py new file mode 100644 index 0000000..73d1f20 --- /dev/null +++ b/photobooth/gui/Qt5Gui/Widgets.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from math import ceil + +from PyQt5 import Qt +from PyQt5 import QtCore +from PyQt5 import QtGui +from PyQt5 import QtWidgets + + +class RoundProgressBar(QtWidgets.QWidget): + # Adaptation of QRoundProgressBar from + # https://sourceforge.net/projects/qroundprogressbar/ + # to PyQt5, using the PyQt4-version offered at + # https://stackoverflow.com/a/33583019 + + def __init__(self, begin, end, value): + + super().__init__() + + self._begin = begin + self._end = end + self._value = value + + self._data_pen_width = 7 + self._outline_pen_width = 10 + self._null_position = 90 + + @property + def value(self): + + return self._value + + @value.setter + def value(self, value): + + if self._value != value: + if value < self._begin: + self._value = self._begin + elif value > self._end: + self._value = self._end + else: + self._value = value + + def _drawBase(self, painter, base_rect): + + color = self.palette().base().color() + color.setAlpha(100) + brush = self.palette().base() + brush.setColor(color) + painter.setPen(QtGui.QPen(self.palette().base().color(), + self._outline_pen_width)) + painter.setBrush(brush) + + painter.drawEllipse(base_rect.adjusted(self._outline_pen_width // 2, + self._outline_pen_width // 2, + -self._outline_pen_width // 2, + -self._outline_pen_width // 2)) + + def _drawCircle(self, painter, base_rect): + + if self.value == self._begin: + return + + arc_length = 360 / (self._end - self._begin) * self.value + + painter.setPen(QtGui.QPen(self.palette().text().color(), + self._data_pen_width)) + painter.setBrush(Qt.Qt.NoBrush) + painter.drawArc(base_rect.adjusted(self._outline_pen_width // 2, + self._outline_pen_width // 2, + -self._outline_pen_width // 2, + -self._outline_pen_width // 2), + self._null_position * 16, -arc_length * 16) + + def _drawText(self, painter, inner_rect, inner_radius): + + text = '{}'.format(ceil(self.value)) + + f = self.font() + f.setPixelSize(inner_radius * 0.8 / len(text)) + painter.setFont(f) + painter.setPen(self.palette().text().color()) + + painter.drawText(inner_rect, Qt.Qt.AlignCenter, text) + + def paintEvent(self, event): + + outer_radius = min(self.width(), self.height()) + inner_radius = outer_radius - self._outline_pen_width + delta = (outer_radius - inner_radius) / 2 + + base_rect = QtCore.QRectF(1, 1, outer_radius - 2, outer_radius - 2) + inner_rect = QtCore.QRectF(delta, delta, inner_radius, inner_radius) + + painter = QtGui.QPainter(self) + painter.setRenderHint(QtGui.QPainter.Antialiasing) + + # base circle + self._drawBase(painter, base_rect) + + # data circle + self._drawCircle(painter, base_rect) + + # text + self._drawText(painter, inner_rect, inner_radius) + + painter.end()