diff --git a/photobooth/gui/Qt5Gui/Frames.py b/photobooth/gui/Qt5Gui/Frames.py index cf80fa7..e49bce3 100644 --- a/photobooth/gui/Qt5Gui/Frames.py +++ b/photobooth/gui/Qt5Gui/Frames.py @@ -316,22 +316,22 @@ class CountdownMessage(QtWidgets.QFrame): class PostprocessMessage(Widgets.TransparentOverlay): - def __init__(self, parent, tasks, idle_handle, timeout=None, - timeout_handle=None): + def __init__(self, parent, tasks, worker, idle_handle, + timeout=None, timeout_handle=None): if timeout_handle is None: timeout_handle = idle_handle super().__init__(parent, timeout, timeout_handle) self.setObjectName('PostprocessMessage') - self.initFrame(tasks, idle_handle) + self.initFrame(tasks, idle_handle, worker) - def initFrame(self, tasks, idle_handle): + def initFrame(self, tasks, idle_handle, worker): def disableAndCall(button, handle): button.setEnabled(False) button.update() - handle() + worker.put(handle) def createButton(task): button = QtWidgets.QPushButton(task.label) diff --git a/photobooth/gui/Qt5Gui/PyQt5Gui.py b/photobooth/gui/Qt5Gui/PyQt5Gui.py index 192d8b9..de05f1d 100644 --- a/photobooth/gui/Qt5Gui/PyQt5Gui.py +++ b/photobooth/gui/Qt5Gui/PyQt5Gui.py @@ -36,6 +36,7 @@ from ..GuiPostprocessor import GuiPostprocessor from . import styles from . import Frames from . import Receiver +from . import Worker class PyQt5Gui(GuiSkeleton): @@ -49,6 +50,7 @@ class PyQt5Gui(GuiSkeleton): is_start, unparsed_args = self._parseArgs() self._initUI(argv[:1] + unparsed_args) self._initReceiver() + self._initWorker() self._picture = None self._postprocess = GuiPostprocessor(self._cfg) @@ -101,6 +103,12 @@ class PyQt5Gui(GuiSkeleton): self._receiver.notify.connect(self.handleState) self._receiver.start() + def _initWorker(self): + + # Create worker thread for time consuming tasks to keep gui responsive + self._worker = Worker.Worker(self._comm) + self._worker.start() + def _enableEscape(self): self._is_escape = True @@ -131,6 +139,7 @@ class PyQt5Gui(GuiSkeleton): if state.target == TeardownEvent.WELCOME: self._comm.send(Workers.MASTER, GuiEvent('welcome')) elif state.target in (TeardownEvent.EXIT, TeardownEvent.RESTART): + self._worker.put(None) self._app.exit(0) def showError(self, state): @@ -229,7 +238,7 @@ class PyQt5Gui(GuiSkeleton): postproc_t = self._cfg.getInt('Photobooth', 'postprocess_time') Frames.PostprocessMessage( - self._gui.centralWidget(), tasks, + self._gui.centralWidget(), tasks, self._worker, lambda: self._comm.send(Workers.MASTER, GuiEvent('idle')), postproc_t * 1000) diff --git a/photobooth/gui/Qt5Gui/Worker.py b/photobooth/gui/Qt5Gui/Worker.py new file mode 100644 index 0000000..28b5a7b --- /dev/null +++ b/photobooth/gui/Qt5Gui/Worker.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Photobooth - a flexible photo booth software +# Copyright (C) 2018 Balthasar Reuter +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import queue + +from PyQt5 import QtCore + + +class Worker(QtCore.QThread): + + def __init__(self, comm): + + super().__init__() + self._comm = comm + self._queue = queue.Queue() + + def put(self, task): + + self._queue.put(task) + + def get(self): + + return self._queue.get() + + def done(self): + + self._queue.task_done() + + def run(self): + + while True: + task = self.get() + if task is None: + break + task() + self.done()