diff --git a/photobooth/Config.py b/photobooth/Config.py index 10cc7e6..6a1d98f 100644 --- a/photobooth/Config.py +++ b/photobooth/Config.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import configparser, os, logging +import configparser +import logging +import os class Config: @@ -14,59 +16,49 @@ class Config: self.defaults() self.read() - @property def filename(self): return self._filename - @filename.setter def filename(self, value): self._filename = value - def defaults(self): filename = os.path.join(os.path.dirname(__file__), 'defaults.cfg') logging.info('Reading config file "%s"', filename) self._cfg.read(filename) - def read(self): logging.info('Reading config file "%s"', self._filename) self._cfg.read(self._filename) - def write(self): logging.info('Writing config file "%s"', self._filename) with open(self._filename, 'w') as configfile: self._cfg.write(configfile) - def get(self, section, key): return self._cfg[section][key] - def getInt(self, section, key): return self._cfg.getint(section, key) - def getFloat(self, section, key): return self._cfg.getfloat(section, key) - def getBool(self, section, key): return self._cfg.getboolean(section, key) - def set(self, section, key, value): self._cfg[section][key] = value diff --git a/photobooth/Gpio.py b/photobooth/Gpio.py index 0c0b91d..134f24e 100644 --- a/photobooth/Gpio.py +++ b/photobooth/Gpio.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from gpiozero import LED, Button +from gpiozero import LED, Button + class Gpio: @@ -10,29 +11,24 @@ class Gpio: self._buttons = [] self._lamps = [] - def setButton(self, bcm_pin, handler): self._buttons.append(Button(bcm_pin)) self._buttons[-1].when_pressed = handler - def setLamp(self, bcm_pin): self._lamps.append(LED(bcm_pin)) return len(self._lamps) - 1 - def lampOn(self, index): self._lamps[index].on() - def lampOff(self, index): self._lamps[index].off() - def lampToggle(self, index): self._lamps[index].toggle() diff --git a/photobooth/Photobooth.py b/photobooth/Photobooth.py index 1b6475f..b297983 100644 --- a/photobooth/Photobooth.py +++ b/photobooth/Photobooth.py @@ -33,46 +33,43 @@ class Photobooth: self.triggerOff() - def initCamera(self, config, camera): self._cap = camera self._pic_dims = PictureDimensions(config, self._cap.getPicture().size) - if ( config.getBool('Photobooth', 'show_preview') - and self._cap.hasPreview ): + if (config.getBool('Photobooth', 'show_preview') + and self._cap.hasPreview): logging.info('Countdown with preview activated') self._show_counter = self.showCounterPreview else: logging.info('Countdown without preview activated') self._show_counter = self.showCounterNoPreview - def initGpio(self, config): - + if config.getBool('Gpio', 'enable'): lamp_pin = config.getInt('Gpio', 'lamp_pin') trigger_pin = config.getInt('Gpio', 'trigger_pin') exit_pin = config.getInt('Gpio', 'exit_pin') - logging.info('GPIO enabled (lamp_pin=%d, trigger_pin=%d, exit_pin=%d)', - lamp_pin, trigger_pin, exit_pin) + logging.info(('GPIO enabled (lamp_pin=%d, trigger_pin=%d, ' + 'exit_pin=%d)'), lamp_pin, trigger_pin, exit_pin) from Gpio import Gpio self._gpio = Gpio() lamp = self._gpio.setLamp(lamp_pin) - self._lampOn = lambda : self._gpio.lampOn(lamp) - self._lampOff = lambda : self._gpio.lampOff(lamp) + self._lampOn = lambda: self._gpio.lampOn(lamp) + self._lampOff = lambda: self._gpio.lampOff(lamp) self._gpio.setButton(trigger_pin, self.gpioTrigger) self._gpio.setButton(exit_pin, self.gpioExit) else: logging.info('GPIO disabled') - self._lampOn = lambda : None - self._lampOff = lambda : None - + self._lampOn = lambda: None + self._lampOff = lambda: None def teardown(self): @@ -80,7 +77,6 @@ class Photobooth: self.triggerOff() self.setCameraIdle() - def recvEvent(self, expected): event = self._conn.recv() @@ -93,7 +89,6 @@ class Photobooth: return event_idx - def recvAck(self): events = ['ack', 'cancel', 'teardown'] @@ -102,7 +97,6 @@ class Photobooth: logging.info('Teardown of camera requested') raise TeardownException() - def recvTriggered(self): events = ['triggered', 'teardown'] @@ -111,20 +105,17 @@ class Photobooth: logging.info('Teardown of camera requested') raise TeardownException() - @property def showCounter(self): return self._show_counter - def initRun(self): self.setCameraIdle() self._conn.send(gui.IdleState()) self.triggerOn() - def run(self): self.initRun() @@ -140,47 +131,41 @@ class Photobooth: self.trigger() except RuntimeError as e: logging.error('Camera error: %s', str(e)) - self._conn.send( gui.ErrorState('Camera error', str(e)) ) + self._conn.send(gui.ErrorState('Camera error', str(e))) self.recvAck() except TeardownException: self.teardown() return 123 - def setCameraActive(self): self._cap.setActive() - def setCameraIdle(self): if self._cap.hasIdle: self._cap.setIdle() - def showCounterPreview(self): self._conn.send(gui.CountdownState()) while not self._conn.poll(): - self._conn.send( - gui.PreviewState(picture = ImageOps.mirror(self._cap.getPreview())) ) + picture = ImageOps.mirror(self._cap.getPreview()) + self._conn.send(gui.PreviewState(picture=picture)) self.recvAck() - def showCounterNoPreview(self): self._conn.send(gui.CountdownState()) self.recvAck() - def showPose(self): self._conn.send(gui.PoseState()) - def captureSinglePicture(self): self.showCounter() @@ -190,29 +175,26 @@ class Photobooth: self.setCameraActive() return picture - def capturePictures(self): - return [ self.captureSinglePicture() for _ in range(self._pic_dims.totalNumPictures) ] - + return [self.captureSinglePicture() + for _ in range(self._pic_dims.totalNumPictures)] def assemblePictures(self, pictures): - output_image = Image.new('RGB', self._pic_dims.outputSize, (255, 255, 255)) + image = Image.new('RGB', self._pic_dims.outputSize, (255, 255, 255)) for i in range(self._pic_dims.totalNumPictures): - output_image.paste(pictures[i].resize(self._pic_dims.thumbnailSize), - self._pic_dims.thumbnailOffset[i]) - - return output_image + image.paste(pictures[i].resize(self._pic_dims.thumbnailSize), + self._pic_dims.thumbnailOffset[i]) + return image def enqueueWorkerTasks(self, picture): for task in self._worker_list: self._queue.put(task.get(picture)) - def trigger(self): logging.info('Photobooth triggered') @@ -228,7 +210,7 @@ class Photobooth: img = self.assemblePictures(pics) self._conn.send(gui.PictureState(img)) - + self.enqueueWorkerTasks(img) self.setCameraIdle() @@ -237,24 +219,20 @@ class Photobooth: self._conn.send(gui.IdleState()) self.triggerOn() - def gpioTrigger(self): self._gpioTrigger() - def gpioExit(self): self._conn.send(gui.TeardownState()) - def triggerOff(self): self._lampOff() - self._gpioTrigger = lambda : None - + self._gpioTrigger = lambda: None def triggerOn(self): self._lampOn() - self._gpioTrigger = lambda : self._conn.send(gui.TriggerState()) + self._gpioTrigger = lambda: self._conn.send(gui.TriggerState()) diff --git a/photobooth/PictureDimensions.py b/photobooth/PictureDimensions.py index d9cc092..4d72a59 100644 --- a/photobooth/PictureDimensions.py +++ b/photobooth/PictureDimensions.py @@ -1,51 +1,50 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- + class PictureDimensions: def __init__(self, config, capture_size): - self._num_pictures = ( config.getInt('Picture', 'num_x') , - config.getInt('Picture', 'num_y') ) + self._num_pictures = (config.getInt('Picture', 'num_x'), + config.getInt('Picture', 'num_y')) self._capture_size = capture_size - self._output_size = ( config.getInt('Picture', 'size_x') , - config.getInt('Picture', 'size_y') ) + self._output_size = (config.getInt('Picture', 'size_x'), + config.getInt('Picture', 'size_y')) - self._min_distance = ( config.getInt('Picture', 'min_dist_x') , - config.getInt('Picture', 'min_dist_y') ) + self._min_distance = (config.getInt('Picture', 'min_dist_x'), + config.getInt('Picture', 'min_dist_y')) self.computeThumbnailDimensions() - def computeThumbnailDimensions(self): - resize_factor = min( ( ( - ( self.outputSize[i] - (self.numPictures[i] + 1) * self.minDistance[i] ) / - ( self.numPictures[i] * self.captureSize[i]) ) for i in range(2) ) ) + resize_factor = min((((self.outputSize[i] - (self.numPictures[i] + 1) * + self.minDistance[i]) / + (self.numPictures[i] * self.captureSize[i])) + for i in range(2))) - self._thumb_size = tuple( int(self.captureSize[i] * resize_factor) - for i in range(2) ) + self._thumb_size = tuple(int(self.captureSize[i] * resize_factor) + for i in range(2)) - output_picture_dist = tuple( ( self.outputSize[i] - self.numPictures[i] * - self.thumbnailSize[i] ) // (self.numPictures[i] + 1) - for i in range(2) ) + thumb_dist = tuple((self.outputSize[i] - self.numPictures[i] * + self.thumbnailSize[i]) // (self.numPictures[i] + 1) + for i in range(2)) self._thumb_offsets = [] for i in range(self.totalNumPictures): pos = (i % self.numPictures[0], i // self.numPictures[0]) - self._thumb_offsets.append( tuple( - (pos[j] + 1) * output_picture_dist[j] + - pos[j] * self.thumbnailSize[j] for j in range(2) ) ) - + self._thumb_offsets.append(tuple((pos[j] + 1) * thumb_dist[j] + + pos[j] * self.thumbnailSize[j] + for j in range(2))) @property def numPictures(self): return self._num_pictures - @property def totalNumPictures(self): @@ -56,25 +55,21 @@ class PictureDimensions: return self._capture_size - @property def outputSize(self): return self._output_size - @property def minDistance(self): return self._min_distance - @property def thumbnailSize(self): return self._thumb_size - @property def thumbnailOffset(self): diff --git a/photobooth/PictureList.py b/photobooth/PictureList.py index 15eebfb..830a332 100644 --- a/photobooth/PictureList.py +++ b/photobooth/PictureList.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import os, logging +import logging +import os from glob import glob @@ -30,10 +31,10 @@ class PictureList: self.findExistingFiles() - def findExistingFiles(self): - - # Find existing files + """Count number of existing files matchin the given basename + """ + # Find existing files count_pattern = '[0-9]' * self.count_width pictures = glob(self.basename + count_pattern + self.suffix) @@ -48,21 +49,18 @@ class PictureList: # Print initial infos logging.info('Number of last existing file: %d', self.counter) - logging.info('Saving assembled pictures as "%s%s.%s"', self.basename, - self.count_width * 'X', 'jpg') - + logging.info('Saving assembled pictures as "%s%s.%s"', self.basename, + self.count_width * 'X', 'jpg') def getFilename(self, count): - + """Return the file name for a given file number""" return self.basename + str(count).zfill(self.count_width) + self.suffix - def getLast(self): - + """Return the current filename""" return self.getFilename(self.counter) - def getNext(self): - + """Update counter and return the next filename""" self.counter += 1 return self.getFilename(self.counter) diff --git a/photobooth/Worker.py b/photobooth/Worker.py index 48d16d7..c2eb282 100644 --- a/photobooth/Worker.py +++ b/photobooth/Worker.py @@ -15,13 +15,11 @@ class WorkerTask: assert not kwargs - def get(self, picture): raise NotImplementedError() - class PictureSaver(WorkerTask): def __init__(self, config): @@ -29,31 +27,27 @@ class PictureSaver(WorkerTask): super().__init__() path = os.path.join(config.get('Picture', 'basedir'), - config.get('Picture', 'basename')) + config.get('Picture', 'basename')) basename = strftime(path, localtime()) self._pic_list = PictureList(basename) - @staticmethod def do(picture, filename): logging.info('Saving picture as %s', filename) picture.save(filename, 'JPEG') - def get(self, picture): return (self.do, (picture, self._pic_list.getNext())) - class Worker: def __init__(self, config, queue): self._queue = queue - def run(self): for func, args in iter(self._queue.get, 'teardown'): diff --git a/photobooth/__init__.py b/photobooth/__init__.py index c409338..bead903 100644 --- a/photobooth/__init__.py +++ b/photobooth/__init__.py @@ -6,4 +6,3 @@ from .main import main if __name__ == "__main__": sys.exit(main(sys.argv)) - \ No newline at end of file diff --git a/photobooth/__main__.py b/photobooth/__main__.py index 028117c..a31be0e 100644 --- a/photobooth/__main__.py +++ b/photobooth/__main__.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import sys, photobooth +import sys +import photobooth + sys.exit(photobooth.main(sys.argv)) diff --git a/photobooth/camera/CameraGphoto2.py b/photobooth/camera/CameraGphoto2.py index 692a5e2..6dcbe75 100644 --- a/photobooth/camera/CameraGphoto2.py +++ b/photobooth/camera/CameraGphoto2.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import io, logging +import io +import logging from PIL import Image @@ -10,7 +11,6 @@ import gphoto2 as gp from . import Camera - class CameraGphoto2(Camera): def __init__(self): @@ -25,26 +25,24 @@ class CameraGphoto2(Camera): self._setupLogging() self._setupCamera() - def cleanup(self): self._cap.set_config(self._oldconfig) self._cap.exit(self._ctxt) - def _setupLogging(self): gp.error_severity[gp.GP_ERROR] = logging.WARNING gp.check_result(gp.use_python_logging()) - def _setupCamera(self): self._ctxt = gp.Context() self._cap = gp.Camera() self._cap.init(self._ctxt) - logging.info('Camera summary: %s', str(self._cap.get_summary(self._ctxt))) + logging.info('Camera summary: %s', + str(self._cap.get_summary(self._ctxt))) # get configuration tree # self._config = self._cap.get_config() @@ -52,30 +50,30 @@ class CameraGphoto2(Camera): config = self._cap.get_config() # make sure camera format is not set to raw - if 'raw' in config.get_child_by_name('imageformat').get_value().lower(): + imageformat = config.get_child_by_name('imageformat').get_value() + if 'raw' in imageformat.lower(): raise RuntimeError('Camera file format is set to RAW') self._printConfig(config) - @staticmethod def _configTreeToText(tree, indent=0): config_txt = '' - for child in tree.get_children(): + for chld in tree.get_children(): config_txt += indent * ' ' - config_txt += child.get_label() + ' [' + child.get_name() + ']: ' + config_txt += chld.get_label() + ' [' + chld.get_name() + ']: ' - if child.count_children() > 0: - config_txt += '\n' - config_txt += CameraGphoto2._configTreeToText(child, indent + 4) + if chld.count_children() > 0: + config_txt += '\n' + config_txt += CameraGphoto2._configTreeToText(chld, indent + 4) else: - config_txt += str(child.get_value()) + config_txt += str(chld.get_value()) try: choice_txt = ' (' - for c in child.get_choices(): + for c in chld.get_choices(): choice_txt += c + ', ' choice_txt += ')' @@ -86,43 +84,34 @@ class CameraGphoto2(Camera): return config_txt - @staticmethod def _printConfig(config): config_txt = 'Camera configuration:\n' config_txt += CameraGphoto2._configTreeToText(config) logging.info(config_txt) - def setActive(self): config = self._cap.get_config() - # self._config.get_child_by_name('viewfinder').set_value(True) config.get_child_by_name('output').set_value('PC') self._cap.set_config(config) - def setIdle(self): config = self._cap.get_config() - # self._config.get_child_by_name('viewfinder').set_value(False) config.get_child_by_name('output').set_value('Off') self._cap.set_config(config) - def getPreview(self): - # self._config.get_child_by_name('autofocusdrive').set_value(1) - # self._cap.set_config(self._config) camera_file = self._cap.capture_preview() file_data = camera_file.get_data_and_size() return Image.open(io.BytesIO(file_data)) - def getPicture(self): - + file_path = self._cap.capture(gp.GP_CAPTURE_IMAGE) - camera_file = self._cap.file_get(file_path.folder, file_path.name, gp.GP_FILE_TYPE_NORMAL) + camera_file = self._cap.file_get(file_path.folder, file_path.name, + gp.GP_FILE_TYPE_NORMAL) file_data = camera_file.get_data_and_size() return Image.open(io.BytesIO(file_data)) - diff --git a/photobooth/camera/CameraGphoto2Cffi.py b/photobooth/camera/CameraGphoto2Cffi.py index 784eea9..7bbdce3 100644 --- a/photobooth/camera/CameraGphoto2Cffi.py +++ b/photobooth/camera/CameraGphoto2Cffi.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import io, logging +import io +import logging from PIL import Image @@ -23,18 +24,18 @@ class CameraGphoto2Cffi(Camera): self._setupCamera() - def _setupCamera(self): self._cap = gp.Camera() - logging.info('Supported operations: %s', self._cap.supported_operations) + logging.info('Supported operations: %s', + self._cap.supported_operations) - if 'raw' in self._cap.config['imgsettings']['imageformat'].value.lower(): + imageformat = self._cap.config['imgsettings']['imageformat'].value + if 'raw' in imageformat.lower(): raise RuntimeError('Camera file format is set to RAW') self._printConfig(self._cap.config) - @staticmethod def _configTreeToText(config, indent=0): @@ -46,38 +47,33 @@ class CameraGphoto2Cffi(Camera): if hasattr(v, '__len__') and len(v) > 1: config_txt += '\n' - config_txt += CameraGphoto2Cffi._configTreeToText(v, indent + 4) + config_txt += CameraGphoto2Cffi._configTreeToText(v, + indent + 4) else: config_txt += str(v) + '\n' return config_txt - @staticmethod def _printConfig(config): config_txt = 'Camera configuration:\n' config_txt += CameraGphoto2Cffi._configTreeToText(config) logging.info(config_txt) - def setActive(self): self._cap._get_config()['actions']['viewfinder'].set(True) self._cap._get_config()['settings']['output'].set('PC') - def setIdle(self): self._cap._get_config()['actions']['viewfinder'].set(False) self._cap._get_config()['settings']['output'].set('Off') - def getPreview(self): return Image.open(io.BytesIO(self._cap.get_preview())) - def getPicture(self): - - return Image.open(io.BytesIO(self._cap.capture())) + return Image.open(io.BytesIO(self._cap.capture())) diff --git a/photobooth/camera/CameraGphoto2CommandLine.py b/photobooth/camera/CameraGphoto2CommandLine.py index 9aa75e6..c4999ad 100644 --- a/photobooth/camera/CameraGphoto2CommandLine.py +++ b/photobooth/camera/CameraGphoto2CommandLine.py @@ -1,11 +1,15 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +import logging +import os +import subprocess + from PIL import Image -import os, subprocess, logging from . import Camera + class CameraGphoto2CommandLine(Camera): def __init__(self): @@ -26,19 +30,17 @@ class CameraGphoto2CommandLine(Camera): self.setActive() - def setActive(self): - print(self._callGphoto('-a', '/dev/null')) - + self._callGphoto('-a', '/dev/null') def getPicture(self): - + self._callGphoto('--capture-image-and-download', self._tmp_filename) return Image.open(self._tmp_filename) - def _callGphoto(self, action, filename): - cmd = 'gphoto2 --force-overwrite --quiet ' + action + ' --filename ' + filename - return subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + cmd = 'gphoto2 --force-overwrite --quiet {} --filename {}' + return subprocess.check_output(cmd.format(action, filename), + shell=True, stderr=subprocess.STDOUT) diff --git a/photobooth/camera/CameraOpenCV.py b/photobooth/camera/CameraOpenCV.py index 29d3259..2d98ff3 100644 --- a/photobooth/camera/CameraOpenCV.py +++ b/photobooth/camera/CameraOpenCV.py @@ -9,6 +9,7 @@ import cv2 from . import Camera + class CameraOpenCV(Camera): def __init__(self): @@ -22,7 +23,6 @@ class CameraOpenCV(Camera): self._cap = cv2.VideoCapture() - def setActive(self): if not self._cap.isOpened(): @@ -30,20 +30,17 @@ class CameraOpenCV(Camera): if not self._cap.isOpened(): raise RuntimeError('Camera could not be opened') - def setIdle(self): if self._cap.isOpened(): self._cap.release() - def getPreview(self): return self.getPicture() - def getPicture(self): - + self.setActive() status, frame = self._cap.read() if not status: @@ -52,4 +49,3 @@ class CameraOpenCV(Camera): # OpenCV yields frames in BGR format, conversion to RGB necessary. # (See https://stackoverflow.com/a/32270308) return Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) - diff --git a/photobooth/camera/__init__.py b/photobooth/camera/__init__.py index f83a877..20b0465 100644 --- a/photobooth/camera/__init__.py +++ b/photobooth/camera/__init__.py @@ -6,8 +6,9 @@ modules = ( ('python-gphoto2', 'CameraGphoto2', 'CameraGphoto2'), ('gphoto2-cffi', 'CameraGphoto2Cffi', 'CameraGphoto2Cffi'), - ('gphoto2-commandline', 'CameraGphoto2CommandLine', 'CameraGphoto2CommandLine'), - ('opencv', 'CameraOpenCV', 'CameraOpenCV') ) + ('gphoto2-commandline', 'CameraGphoto2CommandLine', + 'CameraGphoto2CommandLine'), + ('opencv', 'CameraOpenCV', 'CameraOpenCV')) class Camera: @@ -17,28 +18,23 @@ class Camera: self.hasPreview = False self.hasIdle = False - def __enter__(self): return self - def __exit__(self, exc_type, exc_value, traceback): self.cleanup() - def cleanup(self): pass - @property def hasPreview(self): return self._has_preview - @hasPreview.setter def hasPreview(self, value): @@ -51,7 +47,6 @@ class Camera: def hasIdle(self): return self._has_idle - @hasIdle.setter def hasIdle(self, value): @@ -61,7 +56,6 @@ class Camera: self._has_idle = value - def setActive(self): if not self.hasIdle: @@ -69,7 +63,6 @@ class Camera: else: raise NotImplementedError() - def setIdle(self): if not self.hasIdle: @@ -77,7 +70,6 @@ class Camera: raise NotImplementedError() - def getPreview(self): if not self.hasPreview: @@ -85,15 +77,6 @@ class Camera: raise NotImplementedError() - def getPicture(self): raise NotImplementedError() - - - def setIdle(self): - - if not self.hasIdle: - raise RuntimeError('Camera does not support idle state') - - raise NotImplementedError() diff --git a/photobooth/gui/GuiPostprocess.py b/photobooth/gui/GuiPostprocess.py index 789497e..c966223 100644 --- a/photobooth/gui/GuiPostprocess.py +++ b/photobooth/gui/GuiPostprocess.py @@ -3,31 +3,26 @@ import logging -from PyQt5.QtWidgets import QMessageBox - from .. import printer from ..util import lookup_and_import from .GuiState import PrintState + class GuiPostprocess: def __init__(self, **kwargs): assert not kwargs - def get(self, picture): raise NotImplementedError() - def confirm(self, picture): raise NotImplementedError() - - class PrintPostprocess(GuiPostprocess): def __init__(self, printer_module, page_size, **kwargs): @@ -37,16 +32,13 @@ class PrintPostprocess(GuiPostprocess): Printer = lookup_and_import(printer.modules, printer_module, 'printer') self._printer = Printer(page_size) - def get(self, picture): - return PrintState(lambda : self.do(picture), False) - + return PrintState(lambda: self.do(picture), False) def confirm(self, picture): - return PrintState(lambda : None, True) - + return PrintState(lambda: None, True) def do(self, picture): diff --git a/photobooth/gui/GuiState.py b/photobooth/gui/GuiState.py index 6209424..433460f 100644 --- a/photobooth/gui/GuiState.py +++ b/photobooth/gui/GuiState.py @@ -9,7 +9,6 @@ class GuiState: assert not kwargs - class ErrorState(GuiState): def __init__(self, title, message, **kwargs): @@ -18,26 +17,22 @@ class ErrorState(GuiState): self.title = title self.message = message - @property def title(self): return self._title - @title.setter def title(self, title): self._title = title - @property def message(self): return self._message - @message.setter def message(self, message): @@ -59,13 +54,11 @@ class PictureState(GuiState): self.picture = picture - @property def picture(self): return self._pic - @picture.setter def picture(self, picture): @@ -80,13 +73,11 @@ class MessageState(GuiState): self.message = message - @property def message(self): return self._msg - @message.setter def message(self, message): @@ -154,13 +145,11 @@ class PrintState(GuiState): self.handler = handler self.confirmed = confirmed - @property def handler(self): return self._handler - @handler.setter def handler(self, handler): @@ -169,7 +158,6 @@ class PrintState(GuiState): self._handler = handler - @property def confirmed(self): @@ -182,4 +170,3 @@ class PrintState(GuiState): raise ValueError('confirmed status must be bool') self._confirmed = confirmed - \ No newline at end of file diff --git a/photobooth/gui/PyQt5Gui.py b/photobooth/gui/PyQt5Gui.py index ace6b4e..b1d1515 100644 --- a/photobooth/gui/PyQt5Gui.py +++ b/photobooth/gui/PyQt5Gui.py @@ -8,21 +8,15 @@ from os.path import expanduser from PIL import ImageQt -from PyQt5.QtCore import Qt, QObject, QPoint, QThread, QTimer, pyqtSignal -from PyQt5.QtWidgets import (QFileDialog, QTabWidget, QApplication, QCheckBox, QComboBox, QFormLayout, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLayout, QLineEdit, QMainWindow, QMessageBox, QPushButton, QVBoxLayout, QWidget) -from PyQt5.QtGui import QImage, QPainter, QPixmap +from PyQt5 import QtGui, QtCore, QtWidgets import math -from PyQt5.QtGui import QBrush, QPen, QColor, QFont -from PyQt5.QtCore import QRect from .PyQt5GuiHelpers import QRoundProgressBar from . import * from .. import camera, printer -from ..printer.PrinterPyQt5 import PrinterPyQt5 as Printer - class PyQt5Gui(Gui): @@ -33,7 +27,7 @@ class PyQt5Gui(Gui): global cfg cfg = config - self._app = QApplication(argv) + self._app = QtWidgets.QApplication(argv) self._p = PyQt5MainWindow() self._lastState = self.showStart @@ -94,15 +88,15 @@ class PyQt5Gui(Gui): def handleKeypressEvent(self, event): - if event.key() == Qt.Key_Escape: + if event.key() == QtCore.Qt.Key_Escape: self.handleState(TeardownState()) - elif event.key() == Qt.Key_Space: + elif event.key() == QtCore.Qt.Key_Space: self.handleState(TriggerState()) def handleKeypressEventNoTrigger(self, event): - if event.key() == Qt.Key_Escape: + if event.key() == QtCore.Qt.Key_Escape: self.handleState(TeardownState()) @@ -122,7 +116,7 @@ class PyQt5Gui(Gui): self._p.handleKeypressEvent = self.handleKeypressEventNoTrigger self._p.setCentralWidget( PyQt5GreeterMessage( cfg.getInt('Picture', 'num_x'), cfg.getInt('Picture', 'num_y') ) ) - QTimer.singleShot(cfg.getInt('Photobooth', 'greeter_time') * 1000, self.sendAck) + 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)) @@ -140,7 +134,7 @@ class PyQt5Gui(Gui): elif isinstance(state, PictureState): img = ImageQt.ImageQt(state.picture) self._p.setCentralWidget(PyQt5PictureMessage(img)) - QTimer.singleShot(cfg.getInt('Photobooth', 'display_time') * 1000, + QtCore.QTimer.singleShot(cfg.getInt('Photobooth', 'display_time') * 1000, lambda : self.postprocessPicture(state.picture)) elif isinstance(state, TeardownState): @@ -172,13 +166,13 @@ class PyQt5Gui(Gui): break else: if isinstance(task, PrintState): - reply = QMessageBox.question(self._p, 'Print picture?', + reply = QtWidgets.QMessageBox.question(self._p, 'Print picture?', 'Do you want to print the picture?', - QMessageBox.Yes | QMessageBox.No, QMessageBox.No) - if reply == QMessageBox.Yes: + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) + if reply == QtWidgets.QMessageBox.Yes: task.handler() - QMessageBox.information(self._p, 'Printing', - 'Picture sent to printer.', QMessageBox.Ok) + QtWidgets.QMessageBox.information(self._p, 'Printing', + 'Picture sent to printer.', QtWidgets.QMessageBox.Ok) else: raise ValueError('Unknown task') @@ -188,8 +182,8 @@ class PyQt5Gui(Gui): self._p.handleKeypressEvent = lambda event : None self._lastState = self.showStart self._p.setCentralWidget(PyQt5Start(self)) - if QApplication.overrideCursor() != 0: - QApplication.restoreOverrideCursor() + if QtWidgets.QApplication.overrideCursor() != 0: + QtWidgets.QApplication.restoreOverrideCursor() def showSettings(self): @@ -205,7 +199,7 @@ class PyQt5Gui(Gui): self._conn.send('start') self._p.setCentralWidget(PyQt5WaitMessage('Starting the photobooth...')) if cfg.getBool('Gui', 'hide_cursor'): - QApplication.setOverrideCursor(Qt.BlankCursor) + QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.BlankCursor) def showIdle(self): @@ -218,9 +212,9 @@ class PyQt5Gui(Gui): def showError(self, title, message): logging.error('%s: %s', title, message) - reply = QMessageBox.warning(self._p, title, message, - QMessageBox.Close | QMessageBox.Retry, QMessageBox.Retry) - if reply == QMessageBox.Retry: + reply = QtWidgets.QMessageBox.warning(self._p, title, message, + QtWidgets.QMessageBox.Close | QtWidgets.QMessageBox.Retry, QtWidgets.QMessageBox.Retry) + if reply == QtWidgets.QMessageBox.Retry: self.sendAck() self._lastState() else: @@ -228,9 +222,9 @@ class PyQt5Gui(Gui): self.showStart() -class PyQt5Receiver(QThread): +class PyQt5Receiver(QtCore.QThread): - notify = pyqtSignal(object) + notify = QtCore.pyqtSignal(object) def __init__(self, conn): @@ -257,7 +251,7 @@ class PyQt5Receiver(QThread): -class PyQt5MainWindow(QMainWindow): +class PyQt5MainWindow(QtWidgets.QMainWindow): def __init__(self): @@ -299,10 +293,10 @@ class PyQt5MainWindow(QMainWindow): def closeEvent(self, e): - reply = QMessageBox.question(self, 'Confirmation', "Quit Photobooth?", - QMessageBox.Yes | QMessageBox.No, QMessageBox.No) + reply = QtWidgets.QMessageBox.question(self, 'Confirmation', "Quit Photobooth?", + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) - if reply == QMessageBox.Yes: + if reply == QtWidgets.QMessageBox.Yes: e.accept() else: e.ignore() @@ -315,7 +309,7 @@ class PyQt5MainWindow(QMainWindow): -class PyQt5Start(QFrame): +class PyQt5Start(QtWidgets.QFrame): def __init__(self, gui): @@ -326,28 +320,28 @@ class PyQt5Start(QFrame): def initFrame(self, gui): - grid = QGridLayout() + grid = QtWidgets.QGridLayout() grid.setSpacing(100) self.setLayout(grid) - btnStart = QPushButton('Start Photobooth') + btnStart = QtWidgets.QPushButton('Start Photobooth') btnStart.resize(btnStart.sizeHint()) btnStart.clicked.connect(gui.showStartPhotobooth) grid.addWidget(btnStart, 0, 0) - btnSettings = QPushButton('Settings') + btnSettings = QtWidgets.QPushButton('Settings') btnSettings.resize(btnSettings.sizeHint()) btnSettings.clicked.connect(gui.showSettings) grid.addWidget(btnSettings, 0, 1) - btnQuit = QPushButton('Quit') + btnQuit = QtWidgets.QPushButton('Quit') btnQuit.resize(btnQuit.sizeHint()) btnQuit.clicked.connect(gui.close) grid.addWidget(btnQuit, 0, 2) -class PyQt5Settings(QFrame): +class PyQt5Settings(QtWidgets.QFrame): def __init__(self, gui): @@ -362,7 +356,7 @@ class PyQt5Settings(QFrame): self._value_widgets = {} - layout = QVBoxLayout() + layout = QtWidgets.QVBoxLayout() layout.addWidget(self.createTabs()) layout.addStretch(1) layout.addWidget(self.createButtons()) @@ -371,7 +365,7 @@ class PyQt5Settings(QFrame): def createTabs(self): - tabs = QTabWidget() + tabs = QtWidgets.QTabWidget() tabs.addTab(self.createGuiSettings(), 'Interface') tabs.addTab(self.createPhotoboothSettings(), 'Photobooth') tabs.addTab(self.createCameraSettings(), 'Camera') @@ -384,32 +378,32 @@ class PyQt5Settings(QFrame): def createButtons(self): - layout = QHBoxLayout() + layout = QtWidgets.QHBoxLayout() layout.addStretch(1) - btnSave = QPushButton('Save and restart') + btnSave = QtWidgets.QPushButton('Save and restart') btnSave.resize(btnSave.sizeHint()) btnSave.clicked.connect(self.storeConfigAndRestart) layout.addWidget(btnSave) - btnCancel = QPushButton('Cancel') + btnCancel = QtWidgets.QPushButton('Cancel') btnCancel.resize(btnCancel.sizeHint()) btnCancel.clicked.connect(self._gui.showStart) layout.addWidget(btnCancel) - btnRestore = QPushButton('Restore defaults') + btnRestore = QtWidgets.QPushButton('Restore defaults') btnRestore.resize(btnRestore.sizeHint()) btnRestore.clicked.connect(self.restoreDefaults) layout.addWidget(btnRestore) - widget = QGroupBox() + widget = QtWidgets.QGroupBox() widget.setLayout(layout) return widget def createModuleComboBox(self, module_list, current_module): - cb = QComboBox() + cb = QtWidgets.QComboBox() for m in module_list: cb.addItem(m[0]) @@ -424,30 +418,30 @@ class PyQt5Settings(QFrame): global cfg self._value_widgets['Gui'] = {} - self._value_widgets['Gui']['fullscreen'] = QCheckBox('Enable fullscreen') + self._value_widgets['Gui']['fullscreen'] = QtWidgets.QCheckBox('Enable fullscreen') if cfg.getBool('Gui', 'fullscreen'): self._value_widgets['Gui']['fullscreen'].toggle() self._value_widgets['Gui']['module'] = self.createModuleComboBox(modules, cfg.get('Gui', 'module')) - self._value_widgets['Gui']['width'] = QLineEdit(cfg.get('Gui', 'width')) - self._value_widgets['Gui']['height'] = QLineEdit(cfg.get('Gui', 'height')) - self._value_widgets['Gui']['hide_cursor'] = QCheckBox('Hide cursor') + self._value_widgets['Gui']['width'] = QtWidgets.QLineEdit(cfg.get('Gui', 'width')) + self._value_widgets['Gui']['height'] = QtWidgets.QLineEdit(cfg.get('Gui', 'height')) + self._value_widgets['Gui']['hide_cursor'] = QtWidgets.QCheckBox('Hide cursor') if cfg.getBool('Gui', 'hide_cursor'): self._value_widgets['Gui']['hide_cursor'].toggle() - layout = QFormLayout() + layout = QtWidgets.QFormLayout() layout.addRow(self._value_widgets['Gui']['fullscreen']) - layout.addRow(QLabel('Gui module:'), self._value_widgets['Gui']['module']) + layout.addRow(QtWidgets.QLabel('Gui module:'), self._value_widgets['Gui']['module']) - sublayout_size = QHBoxLayout() - sublayout_size.addWidget(QLabel('Window size [px]:')) + sublayout_size = QtWidgets.QHBoxLayout() + sublayout_size.addWidget(QtWidgets.QLabel('Window size [px]:')) sublayout_size.addWidget(self._value_widgets['Gui']['width']) - sublayout_size.addWidget(QLabel('x')) + sublayout_size.addWidget(QtWidgets.QLabel('x')) sublayout_size.addWidget(self._value_widgets['Gui']['height']) layout.addRow(sublayout_size) layout.addRow(self._value_widgets['Gui']['hide_cursor']) - widget = QWidget() + widget = QtWidgets.QWidget() widget.setLayout(layout) return widget @@ -457,21 +451,20 @@ class PyQt5Settings(QFrame): global cfg self._value_widgets['Gpio'] = {} - self._value_widgets['Gpio']['enable'] = QCheckBox('Enable GPIO') + self._value_widgets['Gpio']['enable'] = QtWidgets.QCheckBox('Enable GPIO') if cfg.getBool('Gpio', 'enable'): self._value_widgets['Gpio']['enable'].toggle() - self._value_widgets['Gpio']['exit_pin'] = QLineEdit(cfg.get('Gpio', 'exit_pin')) - self._value_widgets['Gpio']['trigger_pin'] = QLineEdit(cfg.get('Gpio', 'trigger_pin')) - self._value_widgets['Gpio']['lamp_pin'] = QLineEdit(cfg.get('Gpio', 'lamp_pin')) + self._value_widgets['Gpio']['exit_pin'] = QtWidgets.QLineEdit(cfg.get('Gpio', 'exit_pin')) + self._value_widgets['Gpio']['trigger_pin'] = QtWidgets.QLineEdit(cfg.get('Gpio', 'trigger_pin')) + self._value_widgets['Gpio']['lamp_pin'] = QtWidgets.QLineEdit(cfg.get('Gpio', 'lamp_pin')) - layout = QFormLayout() + layout = QtWidgets.QFormLayout() layout.addRow(self._value_widgets['Gpio']['enable']) - layout.addRow(QLabel('Exit pin (BCM numbering):'), self._value_widgets['Gpio']['exit_pin']) - layout.addRow(QLabel('Trigger pin (BCM numbering):'), self._value_widgets['Gpio']['trigger_pin']) - layout.addRow(QLabel('Lamp pin (BCM numbering):'), self._value_widgets['Gpio']['lamp_pin']) + layout.addRow(QtWidgets.QLabel('Exit pin (BCM numbering):'), self._value_widgets['Gpio']['exit_pin']) + layout.addRow(QtWidgets.QLabel('Trigger pin (BCM numbering):'), self._value_widgets['Gpio']['trigger_pin']) + layout.addRow(QtWidgets.QLabel('Lamp pin (BCM numbering):'), self._value_widgets['Gpio']['lamp_pin']) - # widget = QGroupBox('GPIO settings') - widget = QWidget() + widget = QtWidgets.QWidget() widget.setLayout(layout) return widget @@ -481,26 +474,25 @@ class PyQt5Settings(QFrame): global cfg self._value_widgets['Printer'] = {} - self._value_widgets['Printer']['enable'] = QCheckBox('Enable Printing') + self._value_widgets['Printer']['enable'] = QtWidgets.QCheckBox('Enable Printing') if cfg.getBool('Printer', 'enable'): self._value_widgets['Printer']['enable'].toggle() self._value_widgets['Printer']['module'] = self.createModuleComboBox(printer.modules, cfg.get('Printer', 'module')) - self._value_widgets['Printer']['width'] = QLineEdit(cfg.get('Printer', 'width')) - self._value_widgets['Printer']['height'] = QLineEdit(cfg.get('Printer', 'height')) + self._value_widgets['Printer']['width'] = QtWidgets.QLineEdit(cfg.get('Printer', 'width')) + self._value_widgets['Printer']['height'] = QtWidgets.QLineEdit(cfg.get('Printer', 'height')) - layout = QFormLayout() + layout = QtWidgets.QFormLayout() layout.addRow(self._value_widgets['Printer']['enable']) - layout.addRow(QLabel('Printer module:'), self._value_widgets['Printer']['module']) + layout.addRow(QtWidgets.QLabel('Printer module:'), self._value_widgets['Printer']['module']) - sublayout_size = QHBoxLayout() - sublayout_size.addWidget(QLabel('Paper size [mm]:')) + sublayout_size = QtWidgets.QHBoxLayout() + sublayout_size.addWidget(QtWidgets.QLabel('Paper size [mm]:')) sublayout_size.addWidget(self._value_widgets['Printer']['width']) - sublayout_size.addWidget(QLabel('x')) + sublayout_size.addWidget(QtWidgets.QLabel('x')) sublayout_size.addWidget(self._value_widgets['Printer']['height']) layout.addRow(sublayout_size) - # widget = QGroupBox('Printer settings') - widget = QWidget() + widget = QtWidgets.QWidget() widget.setLayout(layout) return widget @@ -512,11 +504,10 @@ class PyQt5Settings(QFrame): self._value_widgets['Camera'] = {} self._value_widgets['Camera']['module'] = self.createModuleComboBox(camera.modules, cfg.get('Camera', 'module')) - layout = QFormLayout() - layout.addRow(QLabel('Camera module:'), self._value_widgets['Camera']['module']) + layout = QtWidgets.QFormLayout() + layout.addRow(QtWidgets.QLabel('Camera module:'), self._value_widgets['Camera']['module']) - # widget = QGroupBox('Camera settings') - widget = QWidget() + widget = QtWidgets.QWidget() widget.setLayout(layout) return widget @@ -526,21 +517,20 @@ class PyQt5Settings(QFrame): global cfg self._value_widgets['Photobooth'] = {} - self._value_widgets['Photobooth']['show_preview'] = QCheckBox('Show preview while countdown') + self._value_widgets['Photobooth']['show_preview'] = QtWidgets.QCheckBox('Show preview while countdown') if cfg.getBool('Photobooth', 'show_preview'): self._value_widgets['Photobooth']['show_preview'].toggle() - self._value_widgets['Photobooth']['greeter_time'] = QLineEdit(cfg.get('Photobooth', 'greeter_time')) - self._value_widgets['Photobooth']['countdown_time'] = QLineEdit(cfg.get('Photobooth', 'countdown_time')) - self._value_widgets['Photobooth']['display_time'] = QLineEdit(cfg.get('Photobooth', 'display_time')) + self._value_widgets['Photobooth']['greeter_time'] = QtWidgets.QLineEdit(cfg.get('Photobooth', 'greeter_time')) + self._value_widgets['Photobooth']['countdown_time'] = QtWidgets.QLineEdit(cfg.get('Photobooth', 'countdown_time')) + self._value_widgets['Photobooth']['display_time'] = QtWidgets.QLineEdit(cfg.get('Photobooth', 'display_time')) - layout = QFormLayout() + layout = QtWidgets.QFormLayout() layout.addRow(self._value_widgets['Photobooth']['show_preview']) - layout.addRow(QLabel('Greeter time [s]:'), self._value_widgets['Photobooth']['greeter_time']) - layout.addRow(QLabel('Countdown time [s]:'), self._value_widgets['Photobooth']['countdown_time']) - layout.addRow(QLabel('Display time [s]:'), self._value_widgets['Photobooth']['display_time']) + layout.addRow(QtWidgets.QLabel('Greeter time [s]:'), self._value_widgets['Photobooth']['greeter_time']) + layout.addRow(QtWidgets.QLabel('Countdown time [s]:'), self._value_widgets['Photobooth']['countdown_time']) + layout.addRow(QtWidgets.QLabel('Display time [s]:'), self._value_widgets['Photobooth']['display_time']) - # widget = QGroupBox('Photobooth settings') - widget = QWidget() + widget = QtWidgets.QWidget() widget.setLayout(layout) return widget @@ -550,54 +540,54 @@ class PyQt5Settings(QFrame): global cfg self._value_widgets['Picture'] = {} - self._value_widgets['Picture']['num_x'] = QLineEdit(cfg.get('Picture', 'num_x')) - self._value_widgets['Picture']['num_y'] = QLineEdit(cfg.get('Picture', 'num_y')) - self._value_widgets['Picture']['size_x'] = QLineEdit(cfg.get('Picture', 'size_x')) - self._value_widgets['Picture']['size_y'] = QLineEdit(cfg.get('Picture', 'size_y')) - self._value_widgets['Picture']['min_dist_x'] = QLineEdit(cfg.get('Picture', 'min_dist_x')) - self._value_widgets['Picture']['min_dist_y'] = QLineEdit(cfg.get('Picture', 'min_dist_y')) - self._value_widgets['Picture']['basedir'] = QLineEdit(cfg.get('Picture', 'basedir')) - self._value_widgets['Picture']['basename'] = QLineEdit(cfg.get('Picture', 'basename')) + self._value_widgets['Picture']['num_x'] = QtWidgets.QLineEdit(cfg.get('Picture', 'num_x')) + self._value_widgets['Picture']['num_y'] = QtWidgets.QLineEdit(cfg.get('Picture', 'num_y')) + self._value_widgets['Picture']['size_x'] = QtWidgets.QLineEdit(cfg.get('Picture', 'size_x')) + self._value_widgets['Picture']['size_y'] = QtWidgets.QLineEdit(cfg.get('Picture', 'size_y')) + self._value_widgets['Picture']['min_dist_x'] = QtWidgets.QLineEdit(cfg.get('Picture', 'min_dist_x')) + self._value_widgets['Picture']['min_dist_y'] = QtWidgets.QLineEdit(cfg.get('Picture', 'min_dist_y')) + self._value_widgets['Picture']['basedir'] = QtWidgets.QLineEdit(cfg.get('Picture', 'basedir')) + self._value_widgets['Picture']['basename'] = QtWidgets.QLineEdit(cfg.get('Picture', 'basename')) - layout = QFormLayout() + layout = QtWidgets.QFormLayout() - sublayout_num = QHBoxLayout() - sublayout_num.addWidget(QLabel('Number of shots per picture:')) + sublayout_num = QtWidgets.QHBoxLayout() + sublayout_num.addWidget(QtWidgets.QLabel('Number of shots per picture:')) sublayout_num.addWidget(self._value_widgets['Picture']['num_x']) - sublayout_num.addWidget(QLabel('x')) + sublayout_num.addWidget(QtWidgets.QLabel('x')) sublayout_num.addWidget(self._value_widgets['Picture']['num_y']) layout.addRow(sublayout_num) - sublayout_size = QHBoxLayout() - sublayout_size.addWidget(QLabel('Size of assembled picture:')) + sublayout_size = QtWidgets.QHBoxLayout() + sublayout_size.addWidget(QtWidgets.QLabel('Size of assembled picture:')) sublayout_size.addWidget(self._value_widgets['Picture']['size_x']) - sublayout_size.addWidget(QLabel('x')) + sublayout_size.addWidget(QtWidgets.QLabel('x')) sublayout_size.addWidget(self._value_widgets['Picture']['size_y']) layout.addRow(sublayout_size) - sublayout_dist = QHBoxLayout() - sublayout_dist.addWidget(QLabel('Min. distance between shots in picture:')) + sublayout_dist = QtWidgets.QHBoxLayout() + sublayout_dist.addWidget(QtWidgets.QLabel('Min. distance between shots in picture:')) sublayout_dist.addWidget(self._value_widgets['Picture']['min_dist_x']) - sublayout_dist.addWidget(QLabel('x')) + sublayout_dist.addWidget(QtWidgets.QLabel('x')) sublayout_dist.addWidget(self._value_widgets['Picture']['min_dist_y']) layout.addRow(sublayout_dist) file_dialog = lambda : self._value_widgets['Picture']['basedir'].setText( - QFileDialog.getExistingDirectory(self, 'Select directory', - expanduser('~'), QFileDialog.ShowDirsOnly)) - file_button = QPushButton('Select directory') + QtWidgets.QFileDialog.getExistingDirectory(self, 'Select directory', + expanduser('~'), QtWidgets.QFileDialog.ShowDirsOnly)) + file_button = QtWidgets.QPushButton('Select directory') file_button.resize(file_button.sizeHint()) file_button.clicked.connect(file_dialog) - sublayout_path = QHBoxLayout() - sublayout_path.addWidget(QLabel('Basename of output files:')) + sublayout_path = QtWidgets.QHBoxLayout() + sublayout_path.addWidget(QtWidgets.QLabel('Basename of output files:')) sublayout_path.addWidget(self._value_widgets['Picture']['basedir']) - sublayout_path.addWidget(QLabel('/')) + sublayout_path.addWidget(QtWidgets.QLabel('/')) sublayout_path.addWidget(self._value_widgets['Picture']['basename']) sublayout_path.addWidget(file_button) layout.addRow(sublayout_path) - widget = QWidget() + widget = QtWidgets.QWidget() widget.setLayout(layout) return widget @@ -652,7 +642,7 @@ class PyQt5Settings(QFrame): -class PyQt5WaitMessage(QFrame): +class PyQt5WaitMessage(QtWidgets.QFrame): # With spinning wait clock, inspired by # https://wiki.python.org/moin/PyQt/A%20full%20widget%20waiting%20indicator @@ -672,17 +662,17 @@ class PyQt5WaitMessage(QFrame): def paintEvent(self, event): - painter = QPainter(self) + painter = QtGui.QPainter(self) f = self.font() f.setPixelSize(self.height() / 8) painter.setFont(f) - rect = QRect(0, self.height() * 3 / 5, self.width(), self.height() * 3 / 10) - painter.drawText(rect, Qt.AlignCenter, self._message) + rect = QtCore.QRect(0, self.height() * 3 / 5, self.width(), self.height() * 3 / 10) + painter.drawText(rect, QtCore.Qt.AlignCenter, self._message) - painter.setRenderHint(QPainter.Antialiasing) - painter.setPen(QPen(Qt.NoPen)) + painter.setRenderHint(QtGui.QPainter.Antialiasing) + painter.setPen(QtGui.QPen(QtCore.Qt.NoPen)) center = (self.width() / 2, self.height() / 2) @@ -693,7 +683,7 @@ class PyQt5WaitMessage(QFrame): distance = (pos - i) % dots color = (distance + 1) / (dots + 1) * 255 - painter.setBrush(QBrush(QColor(color, color, color))) + painter.setBrush(QtGui.QBrush(QtGui.QColor(color, color, color))) painter.drawEllipse( center[0] + 180 / dots * math.cos(2 * math.pi * i / dots) - 20, @@ -716,7 +706,7 @@ class PyQt5WaitMessage(QFrame): -class PyQt5IdleMessage(QFrame): +class PyQt5IdleMessage(QtWidgets.QFrame): def __init__(self): @@ -732,19 +722,19 @@ class PyQt5IdleMessage(QFrame): def paintEvent(self, event): - painter = QPainter(self) + painter = QtGui.QPainter(self) f = self.font() f.setPixelSize(self.height() / 5) painter.setFont(f) - painter.drawText(event.rect(), Qt.AlignCenter, 'Hit the button!') + painter.drawText(event.rect(), QtCore.Qt.AlignCenter, 'Hit the button!') painter.end() -class PyQt5GreeterMessage(QFrame): +class PyQt5GreeterMessage(QtWidgets.QFrame): def __init__(self, num_x, num_y): @@ -765,24 +755,24 @@ class PyQt5GreeterMessage(QFrame): def paintEvent(self, event): - painter = QPainter(self) + painter = QtGui.QPainter(self) f = self.font() f.setPixelSize(self.height() / 5) painter.setFont(f) - rect = QRect(0, self.height() * 1 / 5, self.width(), self.height() * 3 / 10) - painter.drawText(rect, Qt.AlignCenter, self._title) + rect = QtCore.QRect(0, self.height() * 1 / 5, self.width(), self.height() * 3 / 10) + painter.drawText(rect, QtCore.Qt.AlignCenter, self._title) f.setPixelSize(self.height() / 8) painter.setFont(f) - rect = QRect(0, self.height() * 3 / 5, self.width(), self.height() * 3 / 10) - painter.drawText(rect, Qt.AlignCenter, self._text) + rect = QtCore.QRect(0, self.height() * 3 / 5, self.width(), self.height() * 3 / 10) + painter.drawText(rect, QtCore.Qt.AlignCenter, self._text) painter.end() -class PyQt5CountdownMessage(QFrame): +class PyQt5CountdownMessage(QtWidgets.QFrame): def __init__(self, time, action): @@ -838,28 +828,28 @@ class PyQt5CountdownMessage(QFrame): @picture.setter def picture(self, pic): - if not isinstance(pic, QImage): - raise ValueError('picture must be a QImage') + if not isinstance(pic, QtGui.QImage): + raise ValueError('picture must be a QtGui.QImage') self._picture = pic def paintEvent(self, event): - painter = QPainter(self) + painter = QtGui.QPainter(self) if self._picture != None: - pix = QPixmap.fromImage(self._picture) - pix = pix.scaled(self.size(), Qt.KeepAspectRatio, Qt.FastTransformation) + 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(QPoint(*origin), pix) + 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, QPoint(*offset), self._bar.visibleRegion(), QWidget.DrawChildren) + self._bar.render(self, QtCore.QPoint(*offset), self._bar.visibleRegion(), QtWidgets.QWidget.DrawChildren) def showEvent(self, event): @@ -880,7 +870,7 @@ class PyQt5CountdownMessage(QFrame): -class PyQt5PoseMessage(QFrame): +class PyQt5PoseMessage(QtWidgets.QFrame): def __init__(self): @@ -896,19 +886,19 @@ class PyQt5PoseMessage(QFrame): def paintEvent(self, event): - painter = QPainter(self) + painter = QtGui.QPainter(self) f = self.font() f.setPixelSize(self.height() / 3) painter.setFont(f) - painter.drawText(event.rect(), Qt.AlignCenter, 'Pose!') + painter.drawText(event.rect(), QtCore.Qt.AlignCenter, 'Pose!') painter.end() -class PyQt5PictureMessage(QFrame): +class PyQt5PictureMessage(QtWidgets.QFrame): def __init__(self, picture): @@ -926,17 +916,17 @@ class PyQt5PictureMessage(QFrame): def paintEvent(self, event): - painter = QPainter(self) + painter = QtGui.QPainter(self) - if isinstance(self._picture, QImage): - pix = QPixmap.fromImage(self._picture) + if isinstance(self._picture, QtGui.QImage): + pix = QtGui.QPixmap.fromImage(self._picture) else: - pix = QPixmap(self._picture) - pix = pix.scaled(self.rect().size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) + pix = QtGui.QPixmap(self._picture) + pix = pix.scaled(self.rect().size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) origin = ( (self.rect().width() - pix.width()) // 2, (self.rect().height() - pix.height()) // 2 ) - painter.drawPixmap(QPoint(*origin), pix) + painter.drawPixmap(QtCore.QPoint(*origin), pix) painter.end() diff --git a/photobooth/gui/PyQt5GuiHelpers.py b/photobooth/gui/PyQt5GuiHelpers.py index ff3b5ae..6ce3ce4 100644 --- a/photobooth/gui/PyQt5GuiHelpers.py +++ b/photobooth/gui/PyQt5GuiHelpers.py @@ -10,6 +10,7 @@ from math import ceil from PyQt5 import QtCore, QtGui, Qt, QtWidgets + class QRoundProgressBar(QtWidgets.QWidget): StyleDonut = 1 @@ -33,7 +34,7 @@ class QRoundProgressBar(QtWidgets.QWidget): self.nullPosition = self.PositionTop self.barStyle = self.StyleDonut - self.outlinePenWidth =1 + self.outlinePenWidth = 1 self.dataPenWidth = 1 self.rebuildBrush = False self.format = "%p%" @@ -124,7 +125,8 @@ class QRoundProgressBar(QtWidgets.QWidget): outerRadius = min(self.width(), self.height()) baseRect = QtCore.QRectF(1, 1, outerRadius-2, outerRadius-2) - buffer = QtGui.QImage(outerRadius, outerRadius, QtGui.QImage.Format_ARGB32) + buffer = QtGui.QImage(outerRadius, outerRadius, + QtGui.QImage.Format_ARGB32) buffer.fill(0) p = QtGui.QPainter(buffer) @@ -162,11 +164,13 @@ class QRoundProgressBar(QtWidgets.QWidget): def drawBase(self, p, baseRect): bs = self.barStyle if bs == self.StyleDonut: - p.setPen(QtGui.QPen(self.palette().shadow().color(), self.outlinePenWidth)) + p.setPen(QtGui.QPen(self.palette().shadow().color(), + self.outlinePenWidth)) p.setBrush(self.palette().base()) p.drawEllipse(baseRect) elif bs == self.StylePie: - p.setPen(QtGui.QPen(self.palette().base().color(), self.outlinePenWidth)) + p.setPen(QtGui.QPen(self.palette().base().color(), + self.outlinePenWidth)) p.setBrush(self.palette().base()) p.drawEllipse(baseRect) elif bs == self.StyleLine: @@ -174,13 +178,17 @@ class QRoundProgressBar(QtWidgets.QWidget): color.setAlpha(100) brush = self.palette().base() brush.setColor(color) - p.setPen(QtGui.QPen(self.palette().base().color(), self.outlinePenWidth)) + p.setPen(QtGui.QPen(self.palette().base().color(), + self.outlinePenWidth)) p.setBrush(brush) # p.drawEllipse(baseRect) - # p.setPen(QtGui.QPen(self.palette().base().color(), self.outlinePenWidth)) + # p.setPen(QtGui.QPen(self.palette().base().color(), + # self.outlinePenWidth)) # p.setBrush(Qt.Qt.NoBrush) - p.drawEllipse(baseRect.adjusted(self.outlinePenWidth/2, self.outlinePenWidth/2, -self.outlinePenWidth/2, -self.outlinePenWidth/2)) - + p.drawEllipse(baseRect.adjusted(self.outlinePenWidth/2, + self.outlinePenWidth/2, + -self.outlinePenWidth/2, + -self.outlinePenWidth/2)) def drawValue(self, p, baseRect, value, arcLength): # nothing to draw @@ -189,9 +197,13 @@ class QRoundProgressBar(QtWidgets.QWidget): # for Line style if self.barStyle == self.StyleLine: - p.setPen(QtGui.QPen(self.palette().highlight().color(), self.dataPenWidth)) + p.setPen(QtGui.QPen(self.palette().highlight().color(), + self.dataPenWidth)) p.setBrush(Qt.Qt.NoBrush) - p.drawArc(baseRect.adjusted(self.outlinePenWidth/2, self.outlinePenWidth/2, -self.outlinePenWidth/2, -self.outlinePenWidth/2), + p.drawArc(baseRect.adjusted(self.outlinePenWidth/2, + self.outlinePenWidth/2, + -self.outlinePenWidth/2, + -self.outlinePenWidth/2), self.nullPosition * 16, -arcLength * 16) return @@ -206,7 +218,8 @@ class QRoundProgressBar(QtWidgets.QWidget): dataPath.lineTo(baseRect.center()) p.setBrush(self.palette().highlight()) - p.setPen(QtGui.QPen(self.palette().shadow().color(), self.dataPenWidth)) + p.setPen(QtGui.QPen(self.palette().shadow().color(), + self.dataPenWidth)) p.drawPath(dataPath) def calculateInnerRect(self, baseRect, outerRadius): @@ -239,8 +252,6 @@ class QRoundProgressBar(QtWidgets.QWidget): # !!! to revise f = self.font() - # f.setPixelSize(innerRadius * max(0.05, (0.35 - self.decimals * 0.08))) - # f.setPixelSize(innerRadius * 1.8 / len(text)) f.setPixelSize(innerRadius * 0.8 / len(text)) p.setFont(f) @@ -257,8 +268,8 @@ class QRoundProgressBar(QtWidgets.QWidget): textToDraw = textToDraw.replace("%v", format_string.format(value)) if self.updateFlags & self.UF_PERCENT: - percent = (value - self.min) / (self.max - self.min) * 100.0 - textToDraw = textToDraw.replace("%p", format_string.format(percent)) + perc = (value - self.min) / (self.max - self.min) * 100.0 + textToDraw = textToDraw.replace("%p", format_string.format(perc)) if self.updateFlags & self.UF_MAX: m = self.max - self.min + 1 @@ -267,7 +278,7 @@ class QRoundProgressBar(QtWidgets.QWidget): return textToDraw def valueFormatChanged(self): - self.updateFlags = 0; + self.updateFlags = 0 if "%v" in self.format: self.updateFlags |= self.UF_VALUE @@ -285,7 +296,7 @@ class QRoundProgressBar(QtWidgets.QWidget): self.rebuildBrush = False dataBrush = QtGui.QConicalGradient() - dataBrush.setCenter(0.5,0.5) + dataBrush.setCenter(0.5, 0.5) dataBrush.setCoordinateMode(QtGui.QGradient.StretchToDeviceMode) for pos, color in self.gradientData: @@ -296,4 +307,4 @@ class QRoundProgressBar(QtWidgets.QWidget): p = self.palette() p.setBrush(QtGui.QPalette.Highlight, dataBrush) - self.setPalette(p) \ No newline at end of file + self.setPalette(p) diff --git a/photobooth/gui/__init__.py b/photobooth/gui/__init__.py index 56930fe..374cd3a 100644 --- a/photobooth/gui/__init__.py +++ b/photobooth/gui/__init__.py @@ -1,13 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - -from .GuiState import * -from .GuiPostprocess import * - +from .GuiState import * # noqa +from .GuiPostprocess import * # noqa # Available gui modules as tuples of (config name, module name, class name) -modules = ( ('qt5', 'PyQt5Gui', 'PyQt5Gui'), ) +modules = (('qt5', 'PyQt5Gui', 'PyQt5Gui'), ) class Gui: @@ -16,9 +14,6 @@ class Gui: pass - def run(self, camera_conn, worker_queue): raise NotImplementedError() - - diff --git a/photobooth/main.py b/photobooth/main.py index 0e23b8a..5ec6ad7 100644 --- a/photobooth/main.py +++ b/photobooth/main.py @@ -7,9 +7,10 @@ try: except DistributionNotFound: __version__ = 'unknown' -import sys +import logging +import logging.handlers import multiprocessing as mp -import logging, logging.handlers +import sys from . import camera, gui from .Config import Config @@ -17,6 +18,7 @@ from .Photobooth import Photobooth from .util import lookup_and_import from .Worker import Worker + class CameraProcess(mp.Process): def __init__(self, config, conn, worker_queue): @@ -28,7 +30,6 @@ class CameraProcess(mp.Process): self.conn = conn self.worker_queue = worker_queue - def run_camera(self): try: @@ -40,7 +41,7 @@ class CameraProcess(mp.Process): return photobooth.run() except BaseException as e: - self.conn.send( gui.ErrorState('Camera error', str(e)) ) + self.conn.send(gui.ErrorState('Camera error', str(e))) event = self.conn.recv() if str(event) in ('cancel', 'ack'): return 123 @@ -48,7 +49,6 @@ class CameraProcess(mp.Process): logging.error('Unknown event received: %s', str(event)) raise RuntimeError('Unknown event received', str(event)) - def run(self): status_code = 123 @@ -76,7 +76,6 @@ class WorkerProcess(mp.Process): self.cfg = config self.queue = queue - def run(self): sys.exit(Worker(self.cfg, self.queue).run()) @@ -93,10 +92,10 @@ class GuiProcess(mp.Process): self.conn = conn self.queue = queue - def run(self): - Gui = lookup_and_import(gui.modules, self.cfg.get('Gui', 'module'), 'gui') + Gui = lookup_and_import(gui.modules, self.cfg.get('Gui', 'module'), + 'gui') sys.exit(Gui(self.argv, self.cfg).run(self.conn, self.queue)) @@ -107,7 +106,7 @@ def run(argv): # Load configuration config = Config('photobooth.cfg') - # Create communication objects: + # Create communication objects: # 1. We use a pipe to connect GUI and camera process # 2. We use a queue to feed tasks to the postprocessing process gui_conn, camera_conn = mp.Pipe() @@ -129,7 +128,7 @@ def run(argv): # Close endpoints gui_conn.close() camera_conn.close() - + # Wait for processes to finish gui_proc.join() worker_queue.put('teardown') @@ -150,12 +149,12 @@ def main(argv): ch.setFormatter(formatter) # create file handler and set format - fh = logging.handlers.TimedRotatingFileHandler('photobooth.log', - when='d', interval=1, backupCount=10) + fh = logging.handlers.TimedRotatingFileHandler('photobooth.log', when='d', + interval=1, backupCount=10) fh.setFormatter(formatter) # Apply config - logging.basicConfig(level=log_level, handlers=(ch,fh)) + logging.basicConfig(level=log_level, handlers=(ch, fh)) # Set of known status codes which trigger a restart of the application known_status_codes = { diff --git a/photobooth/printer/PrinterPyQt5.py b/photobooth/printer/PrinterPyQt5.py index 2cea014..948369d 100644 --- a/photobooth/printer/PrinterPyQt5.py +++ b/photobooth/printer/PrinterPyQt5.py @@ -5,12 +5,12 @@ import logging from PIL import ImageQt -from PyQt5.QtCore import Qt, QPoint, QSizeF -from PyQt5.QtGui import QPageSize, QPainter, QPixmap +from PyQt5 import QtCore, QtGui from PyQt5.QtPrintSupport import QPrinter from . import Printer + class PrinterPyQt5(Printer): def __init__(self, page_size, print_pdf=False): @@ -18,7 +18,8 @@ class PrinterPyQt5(Printer): super().__init__(page_size) self._printer = QPrinter(QPrinter.HighResolution) - self._printer.setPageSize(QPageSize(QSizeF(*page_size), QPageSize.Millimeter)) + self._printer.setPageSize(QtGui.QPageSize(QtCore.QSizeF(*page_size), + QtGui.QPageSize.Millimeter)) self._printer.setColorMode(QPrinter.Color) logging.info('Using printer "%s"', self._printer.printerName()) @@ -30,21 +31,21 @@ class PrinterPyQt5(Printer): self._printer.setOutputFormat(QPrinter.PdfFormat) self._printer.setFullPage(True) - def print(self, picture): - + if self._print_pdf: - self._printer.setOutputFileName('print_' + str(self._counter) + '.pdf') + self._printer.setOutputFileName('print_%d.pdf' % self._counter) self._counter += 1 img = ImageQt.ImageQt(picture) - img = img.scaled(self._printer.pageRect().size(), Qt.KeepAspectRatio, - Qt.SmoothTransformation) + img = img.scaled(self._printer.pageRect().size(), + QtCore.Qt.KeepAspectRatio, + QtCore.Qt.SmoothTransformation) printable_size = self._printer.pageRect(QPrinter.DevicePixel) - origin = ( (printable_size.width() - img.width()) // 2, - (printable_size.height() - img.height()) // 2 ) - - painter = QPainter(self._printer) - painter.drawImage(QPoint(*origin), img) + origin = ((printable_size.width() - img.width()) // 2, + (printable_size.height() - img.height()) // 2) + + painter = QtGui.QPainter(self._printer) + painter.drawImage(QtCore.QPoint(*origin), img) painter.end() diff --git a/photobooth/printer/__init__.py b/photobooth/printer/__init__.py index bc291ee..7341a9a 100644 --- a/photobooth/printer/__init__.py +++ b/photobooth/printer/__init__.py @@ -13,13 +13,11 @@ class Printer: self.pageSize = page_size - @property def pageSize(self): return self._page_size - @pageSize.setter def pageSize(self, page_size): @@ -28,8 +26,6 @@ class Printer: self._page_size = page_size - def print(self, picture): raise NotImplementedError('print function not implemented!') - \ No newline at end of file diff --git a/photobooth/util.py b/photobooth/util.py index ad42e60..2881102 100644 --- a/photobooth/util.py +++ b/photobooth/util.py @@ -1,23 +1,22 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - import importlib def lookup_and_import(module_list, name, package=None): - result = next(((mod_name, class_name) - for config_name, mod_name, class_name in module_list - if name == config_name), None) - - if package == None: + result = next(((mod_name, class_name) + for config_name, mod_name, class_name in module_list + if name == config_name), None) + + if package is None: import_module = importlib.import_module('photobooth.' + result[0]) else: import_module = importlib.import_module( 'photobooth.' + package + '.' + result[0]) - if result[1] == None: + if result[1] is None: return import_module else: return getattr(import_module, result[1])