flake8 compliance (except for PyQt5Gui)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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):
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'):
|
||||
|
||||
@@ -6,4 +6,3 @@ from .main import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys, photobooth
|
||||
import sys
|
||||
import photobooth
|
||||
|
||||
sys.exit(photobooth.main(sys.argv))
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
self.setPalette(p)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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!')
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user