Initial commit for the more modular rewrite of the Photobooth.

Basic Qt5-GUI implemented
Config-File support implemented
Basic settings dialog to change config implemented
NO Photobooth functionality, yet
This commit is contained in:
Balthasar Reuter
2018-03-17 14:54:08 +01:00
parent 1da57c5bfc
commit ade6d05aee
7 changed files with 371 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
photobooth.cfg
photobooth/__pycache__

68
photobooth/Config.py Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import configparser, os
class Config:
def __init__(self, filename):
self._filename = filename
self._cfg = configparser.ConfigParser()
self.defaults()
self.read()
@property
def filename(self):
return self._filename
@filename.setter
def filename(self, value):
self._filename = value
def defaults(self):
self._cfg.read(os.path.join(os.path.dirname(__file__), 'defaults.cfg'))
def read(self):
self._cfg.read(self._filename)
def write(self):
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

9
photobooth/Photobooth.py Normal file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import Config, PyQt5Gui
def main(argv):
config = Config.Config('photobooth.cfg')
return PyQt5Gui.run(argv, config)

257
photobooth/PyQt5Gui.py Normal file
View File

@@ -0,0 +1,257 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QFormLayout, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLayout, QLineEdit, QMainWindow, QMessageBox, QPushButton, QVBoxLayout)
class PyQt5Gui(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
global cfg
self.showStart()
self.setWindowTitle('Photobooth')
if cfg.getBool('Gui', 'fullscreen'):
self.showFullScreen()
else:
self.resize(cfg.getInt('Gui', 'width'),
cfg.getInt('Gui', 'height'))
self.show()
def showStart(self):
content = PyQt5Start(self)
self.setCentralWidget(content)
def showSettings(self):
content = PyQt5Settings(self)
self.setCentralWidget(content)
def closeEvent(self, e):
reply = QMessageBox.question(self, 'Confirmation', "Quit Photobooth?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
e.accept()
else:
e.ignore()
def keyPressEvent(self, e):
pass
# if self.photobooth.status == Status.idle:
# if e.key() == Qt.Key_Escape:
# self.showStart()
# elif e.key() == Qt.Key_Space:
# self.centralWidget().trigger()
class PyQt5Start(QFrame):
def __init__(self, parent):
super().__init__(parent)
self.initFrame(parent)
def initFrame(self, parent):
grid = QGridLayout()
grid.setSpacing(100)
self.setLayout(grid)
btnStart = QPushButton('Start Photobooth')
btnStart.resize(btnStart.sizeHint())
# btnStart.clicked.connect(parent.showPhotobooth)
grid.addWidget(btnStart, 0, 0)
btnSettings = QPushButton('Settings')
btnSettings.resize(btnSettings.sizeHint())
btnSettings.clicked.connect(parent.showSettings)
grid.addWidget(btnSettings, 0, 1)
btnQuit = QPushButton('Quit')
btnQuit.resize(btnQuit.sizeHint())
btnQuit.clicked.connect(parent.close)
grid.addWidget(btnQuit, 0, 2)
class PyQt5Settings(QFrame):
def __init__(self, parent):
super().__init__(parent)
self._parent = parent
self.initFrame()
def initFrame(self):
self._value_widgets = {}
grid = QGridLayout()
grid.addWidget(self.createGuiSettings(), 0, 0)
grid.addWidget(self.createGpioSettings(), 1, 0)
grid.addWidget(self.createCameraSettings(), 0, 1)
layout = QVBoxLayout()
layout.addLayout(grid)
layout.addStretch(1)
layout.addWidget(self.createButtons())
self.setLayout(layout)
def createGuiSettings(self):
global cfg
self._value_widgets['Gui'] = {}
self._value_widgets['Gui']['fullscreen'] = QCheckBox('Enable fullscreen')
if cfg.getBool('Gui', 'fullscreen'):
self._value_widgets['Gui']['fullscreen'].toggle()
self._value_widgets['Gui']['width'] = QLineEdit(cfg.get('Gui', 'width'))
self._value_widgets['Gui']['height'] = QLineEdit(cfg.get('Gui', 'height'))
layout = QFormLayout()
layout.addRow(self._value_widgets['Gui']['fullscreen'])
layout.addRow(QLabel('Width:'), self._value_widgets['Gui']['width'])
layout.addRow(QLabel('Height:'), self._value_widgets['Gui']['height'])
widget = QGroupBox('Interface settings (restart required)')
widget.setLayout(layout)
return widget
def createGpioSettings(self):
global cfg
self._value_widgets['Gpio'] = {}
self._value_widgets['Gpio']['enable'] = QCheckBox('Enable GPIO (restart required)')
if cfg.getBool('Gpio', 'enable'):
self._value_widgets['Gpio']['enable'].toggle()
self._value_widgets['Gpio']['exit_channel'] = QLineEdit(cfg.get('Gpio', 'exit_channel'))
self._value_widgets['Gpio']['trigger_channel'] = QLineEdit(cfg.get('Gpio', 'trigger_channel'))
self._value_widgets['Gpio']['lamp_channel'] = QLineEdit(cfg.get('Gpio', 'lamp_channel'))
layout = QFormLayout()
layout.addRow(self._value_widgets['Gpio']['enable'])
layout.addRow(QLabel('Exit channel:'), self._value_widgets['Gpio']['exit_channel'])
layout.addRow(QLabel('Trigger channel'), self._value_widgets['Gpio']['trigger_channel'])
layout.addRow(QLabel('Lamp channel'), self._value_widgets['Gpio']['lamp_channel'])
widget = QGroupBox('GPIO settings')
widget.setLayout(layout)
return widget
def createCameraSettings(self):
global cfg
wrapper = QComboBox()
wrapper.addItem('command line')
wrapper.addItem('piggyphoto')
wrapper.addItem('gphoto2-cffi')
current_wrapper = cfg.get('Camera', 'gphoto2_wrapper')
if current_wrapper == 'commandline':
wrapper.setCurrentIndex(0)
elif current_wrapper == 'piggyphoto':
wrapper.setCurrentIndex(1)
elif current_wrapper == 'gphoto2-cffi':
wrapper.setCurrentIndex(2)
else:
wrapper.setCurrentIndex(-1)
self._value_widgets['Camera'] = {}
self._value_widgets['Camera']['gphoto2_wrapper'] = wrapper
layout = QFormLayout()
layout.addRow(QLabel('gPhoto2 wrapper:'), self._value_widgets['Camera']['gphoto2_wrapper'])
widget = QGroupBox('Camera settings')
widget.setLayout(layout)
return widget
def createButtons(self):
layout = QHBoxLayout()
layout.addStretch(1)
btnSave = QPushButton('Save')
btnSave.resize(btnSave.sizeHint())
btnSave.clicked.connect(self.storeConfig)
layout.addWidget(btnSave)
btnCancel = QPushButton('Cancel')
btnCancel.resize(btnCancel.sizeHint())
btnCancel.clicked.connect(self._parent.showStart)
layout.addWidget(btnCancel)
btnRestore = QPushButton('Restore defaults')
btnRestore.resize(btnRestore.sizeHint())
btnRestore.clicked.connect(self.restoreDefaults)
layout.addWidget(btnRestore)
widget = QGroupBox()
widget.setLayout(layout)
return widget
def storeConfig(self):
global cfg
cfg.set('Gui', 'fullscreen', str(self._value_widgets['Gui']['fullscreen'].isChecked()))
cfg.set('Gui', 'width', self._value_widgets['Gui']['width'].text())
cfg.set('Gui', 'height', self._value_widgets['Gui']['height'].text())
cfg.set('Gpio', 'enable', str(self._value_widgets['Gpio']['enable'].isChecked()))
cfg.set('Gpio', 'exit_channel', self._value_widgets['Gpio']['exit_channel'].text())
cfg.set('Gpio', 'trigger_channel', self._value_widgets['Gpio']['trigger_channel'].text())
cfg.set('Gpio', 'lamp_channel', self._value_widgets['Gpio']['lamp_channel'].text())
wrapper_idx2val = [ 'commandline', 'piggyphoto', 'gphoto2-cffi' ]
cfg.set('Camera', 'gphoto2_wrapper', wrapper_idx2val[self._value_widgets['Camera']['gphoto2_wrapper'].currentIndex()])
cfg.write()
self._parent.showStart()
def restoreDefaults(self):
global cfg
cfg.defaults()
self._parent.showSettings()
def run(argv, config):
global cfg
cfg = config
app = QApplication(argv)
p = PyQt5Gui()
return app.exec_()

8
photobooth/__init__.py Normal file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, Photobooth
if __name__ == "__main__":
sys.exit(Photobooth.main(sys.argv))

6
photobooth/__main__.py Normal file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, Photobooth
sys.exit(Photobooth.main(sys.argv))

21
photobooth/defaults.cfg Normal file
View File

@@ -0,0 +1,21 @@
[Gui]
# Start Photobooth in fullscreen mode (True/False)
fullscreen = False
# Width of Photobooth (if not fullscreen)
width = 1024
# Height of Photobooth (if not fullscreen)
height = 600
[Camera]
# Wrapper to use gPhoto2 (gphoto2-cffi, piggyphoto, commandline)
gphoto2_wrapper = commandline
[Gpio]
# Enable use of GPIO (True/False)
enable = True
# Pin 18 (Channel 24) lets you return to start screen
exit_channel = 24
# Pin 16 (Channel 23) triggers capturing pictures
trigger_channel = 23
# Pin 7 (Channel 4) switches the lamp on and off
lamp_channel = 4