FotoBox
FotoBox::FotoBox Class Reference

The FotoBox class Main class to control UI and controll the process. More...

#include <fotobox.h>

+ Inheritance diagram for FotoBox::FotoBox:
+ Collaboration diagram for FotoBox::FotoBox:

Signals

void start ()
 signal: start FotoBox More...
 
void startBuzzer ()
 signal: start query pin with Buzzer class More...
 

Public Member Functions

 FotoBox (QWidget *parent=nullptr)
 FotoBox constructor. More...
 
 ~FotoBox () override
 FotoBox destructor. More...
 
 FotoBox (const FotoBox &other)=delete
 FotoBox default copy constructor. More...
 
FotoBoxoperator= (const FotoBox &other)=delete
 FotoBox default copy assignment. More...
 
 FotoBox (FotoBox &&other)=delete
 FotoBox default move constructor. More...
 
FotoBoxoperator= (FotoBox &&other)=delete
 FotoBox default move assignment. More...
 

Private Slots

void photo ()
 trigger camera to shot a photo and try to show it More...
 
void preferenceDialog ()
 show preference dialog and close dialog More...
 

Private Member Functions

void closeFullscreenWindowOnMac ()
 Is used as a workaround for macOS to close a fullscreen window. More...
 
void keyPressEvent (QKeyEvent *event) override
 filter key press events More...
 
void mouseReleaseEvent (QMouseEvent *event) override
 This event handler, for event event, can be reimplemented in a subclass to receive mouse release events for the widget. More...
 
void buttons ()
 With or without buttons. More...
 
void countdown ()
 With or without countdown. More...
 
void buzzer ()
 creates a new Buzzer object More...
 
void loadPhoto (const QString &i_filePath)
 try to load the photo to QPixmap More...
 
void drawText (const QString &i_text)
 Draw text on the QPixmap. More...
 

Static Private Member Functions

static auto calculateFontSize (double i_width, double i_widthFont) -> double
 calculate "maximum" fitting font size More...
 

Private Attributes

Ui::FotoBoxDialog * m_ui
 
Countdown m_countdown
 
QThread m_workerThread
 
Buzzer m_buzzer
 
Camera m_camera
 
QPixmap m_photo
 
const QString m_photoDir
 
const std::vector< Qt::Key > m_triggerKey {Qt::Key_N, Qt::Key_Return, Qt::Key_Enter, Qt::Key_PageDown, Qt::Key_PageUp, Qt::Key_Left, Qt::Key_Right, Qt::Key_Up, Qt::Key_Down, Qt::Key_Space, Qt::Key_Backspace}
 
const std::vector< Qt::Key > m_preferenceKey {Qt::Key_P, Qt::Key_S, Qt::Key_E}
 
const std::vector< Qt::Key > m_quitKey {Qt::Key_Escape, Qt::Key_Q}
 

Static Private Attributes

static constexpr int STATUSBAR_MSG_TIMEOUT = 8000
 
static constexpr double COMPARE = 1.25
 

Detailed Description

The FotoBox class Main class to control UI and controll the process.

Definition at line 30 of file fotobox.h.

Constructor & Destructor Documentation

◆ FotoBox() [1/3]

FotoBox::FotoBox::FotoBox ( QWidget *  parent = nullptr)
explicit

FotoBox constructor.

Parameters
parentQWidget

Definition at line 21 of file fotobox.cpp.

22  : QDialog(parent)
23  , m_ui(new Ui::FotoBoxDialog)
24  , m_countdown(this)
25  , m_workerThread(this)
26  , m_camera(this)
27  , m_photoDir(PreferenceProvider::instance().photoFolder() + QDir::separator())
28 {
29  //setup GUI
30  m_ui->setupUi(this);
31 
32  //e.g. 'FotoBox v1.2.3 (Copyright 2016 Thomas Kais)'
33  setWindowTitle(QStringLiteral("%1 v%2 (Copyright 2016 %3)").arg(QApplication::applicationName(), QApplication::applicationVersion(), QApplication::organizationName()));
34 
35  //set Background Color
36  setStyleSheet(QStringLiteral("#FotoBoxDialog { background-color:%1; }").arg(PreferenceProvider::instance().backgroundColor()));
37 
38  //delete everything on close
39  setAttribute(Qt::WA_DeleteOnClose);
40 
41  //show QStatusBar only when needed (safe space for the photos)
42  connect(m_ui->statusBar, &QStatusBar::messageChanged, this, [&](const QString &i_message) { i_message.isNull() ? m_ui->statusBar->hide() : m_ui->statusBar->show(); });
43  //hide status bar (ATTENTION: don't use at other places, see connect line above)
44  m_ui->statusBar->hide();
45 
46  //with or without buttons?
47  buttons();
48 
49  //Buzzer class (Raspberry Pi GPIO using pigpio)
50 #if defined(BUZZER_AVAILABLE)
51  if (PreferenceProvider::instance().queryInterval() > 0) {
52  buzzer();
53  }
54 #endif
55 
56  //countdown?
57  countdown();
58 }
void countdown()
With or without countdown.
Definition: fotobox.cpp:106
QThread m_workerThread
Definition: fotobox.h:148
const QString m_photoDir
Definition: fotobox.h:160
Camera m_camera
Definition: fotobox.h:154
Ui::FotoBoxDialog * m_ui
Definition: fotobox.h:142
void buzzer()
creates a new Buzzer object
Definition: fotobox.cpp:77
Countdown m_countdown
Definition: fotobox.h:145
void buttons()
With or without buttons.
Definition: fotobox.cpp:60
static PreferenceProvider & instance()
get instance (Meyers Singleton)

References FotoBox::PreferenceProvider::instance().

+ Here is the call graph for this function:

◆ ~FotoBox()

FotoBox::FotoBox::~FotoBox ( )
override

FotoBox destructor.

Definition at line 135 of file fotobox.cpp.

136 {
137 #if defined(BUZZER_AVAILABLE)
138  if (PreferenceProvider::instance().queryInterval() > 0) {
139  //stop query pin
140  m_buzzer.stop();
141  }
142 #endif
143  //terminate and delete Buzzer thread
144  m_workerThread.quit();
145  m_workerThread.wait();
146 
147  delete m_ui;
148 }
void stop()
Stop executing.
Definition: buzzer.cpp:86
Buzzer m_buzzer
Definition: fotobox.h:151

References FotoBox::PreferenceProvider::instance().

+ Here is the call graph for this function:

◆ FotoBox() [2/3]

FotoBox::FotoBox::FotoBox ( const FotoBox other)
delete

FotoBox default copy constructor.

◆ FotoBox() [3/3]

FotoBox::FotoBox::FotoBox ( FotoBox &&  other)
delete

FotoBox default move constructor.

Member Function Documentation

◆ buttons()

void FotoBox::FotoBox::buttons ( )
private

With or without buttons.

Definition at line 60 of file fotobox.cpp.

61 {
62  if (PreferenceProvider::instance().showButtons()) {
63  //connect buttons
64  connect(m_ui->btnStart, &QPushButton::clicked, this, &FotoBox::start);
65  connect(m_ui->btnPreferencesDialog, &QPushButton::clicked, this, &FotoBox::preferenceDialog);
66  connect(m_ui->btnQuitApp, &QPushButton::clicked, QCoreApplication::instance(), &QCoreApplication::quit);
67  } else {
68  //hide mouse cursor
69  QGuiApplication::setOverrideCursor(Qt::BlankCursor);
70  //hide buttons
71  m_ui->btnStart->hide();
72  m_ui->btnPreferencesDialog->hide();
73  m_ui->btnQuitApp->hide();
74  }
75 }

References FotoBox::PreferenceProvider::instance().

+ Here is the call graph for this function:

◆ buzzer()

void FotoBox::FotoBox::buzzer ( )
private

creates a new Buzzer object

Definition at line 77 of file fotobox.cpp.

78 {
79 #if defined(BUZZER_AVAILABLE)
80  if (m_workerThread.isRunning()) {
81  return;
82  }
83 
84  if (!m_buzzer.initialise()) {
85  //pigpio init not successfull
86  m_ui->statusBar->showMessage(tr("Buzzer isn't working. Please check 'pigpio' deamon."), STATUSBAR_MSG_TIMEOUT);
87  return;
88  }
89 
90  //move to a thread
91  m_buzzer.moveToThread(&m_workerThread);
92 
93  //connect the start signal for buzzer
94  connect(this, &FotoBox::startBuzzer, &m_buzzer, &Buzzer::queryPin);
95  //start fotobox if buzzer was triggered
96  connect(&m_buzzer, &Buzzer::triggered, this, &FotoBox::start);
97 
98  m_workerThread.start();
99 
100  //start query
101  emit startBuzzer();
102 #endif
103 }
void queryPin()
Query the Raspberry Pi pin.
Definition: buzzer.cpp:79
auto initialise() -> bool
Initialises the library and sets the GPIO mode.
Definition: buzzer.cpp:77
void triggered()
Buzzer was pressed.
void startBuzzer()
signal: start query pin with Buzzer class
static constexpr int STATUSBAR_MSG_TIMEOUT
Definition: fotobox.h:136

References FotoBox::Buzzer::queryPin(), and FotoBox::Buzzer::triggered().

+ Here is the call graph for this function:

◆ calculateFontSize()

auto FotoBox::FotoBox::calculateFontSize ( double  i_width,
double  i_widthFont 
) -> double
staticprivate

calculate "maximum" fitting font size

Parameters
i_widthdouble
i_widthFontdouble
Returns
best fitting fontsize

Definition at line 280 of file fotobox.cpp.

281 {
282  auto factor = i_width / i_widthFont;
283  if ((factor < 1) || (factor > COMPARE)) {
284  return factor;
285  }
286  return 0.0;
287 }
static constexpr double COMPARE
Definition: fotobox.h:139

◆ closeFullscreenWindowOnMac()

void FotoBox::FotoBox::closeFullscreenWindowOnMac ( )
private

Is used as a workaround for macOS to close a fullscreen window.

close the window again, using the native MacOS API (https://bugreports.qt.io/browse/QTBUG-46701)

Definition at line 16 of file fotoboxmac.mm.

17 {
18  //WORKAROUND QTBUG-36714: closing a full screen QMainWindow leaves the screen black on macOS if there are multiple instances of QMainWindow created
19  const auto *view = reinterpret_cast<NSView *>(winId());
20  if (view == nil) {
21  return;
22  }
23 
24  const auto *window = view.window;
25  if (window == nil) {
26  return;
27  }
28 
29  //close the window again, using the native MacOS API
30  [window close];
31 }

◆ countdown()

void FotoBox::FotoBox::countdown ( )
private

With or without countdown.

Definition at line 106 of file fotobox.cpp.

107 {
108  //initialize countdown
109  m_ui->lcdCountdown->hide();
110 
112  //add countdown
113  m_countdown.setStartTime(static_cast<unsigned int>(PreferenceProvider::instance().countdown()));
114  connect(this, &FotoBox::start, &m_countdown, &Countdown::start);
115  connect(&m_countdown, &Countdown::elapsed, this, &FotoBox::photo);
116 
117  //update UI
118  connect(&m_countdown, &Countdown::update, this, [&](const unsigned int i_timeLeft) {
119  //hide photo and show countdown
120  m_ui->lblPhoto->hide();
121  m_ui->lcdCountdown->show();
122  m_ui->lcdCountdown->display(QString::number(i_timeLeft));
123  });
124 
125  //apply font color
126  auto palette = m_ui->lcdCountdown->palette();
127  palette.setColor(QPalette::WindowText, PreferenceProvider::instance().countdownColor());
128  m_ui->lcdCountdown->setPalette(palette);
129  } else {
130  //disable countdown
131  connect(this, &FotoBox::start, this, &FotoBox::photo);
132  }
133 }
void setStartTime(unsigned int i_seconds)
Set the countdown start time.
Definition: countdown.cpp:46
auto start() -> bool
Start countdown.
Definition: countdown.cpp:57
void elapsed()
Countdown elapsed.
void update(unsigned int)
Update countdown.

References FotoBox::Countdown::elapsed(), FotoBox::PreferenceProvider::instance(), FotoBox::Countdown::start(), and FotoBox::Countdown::update().

+ Here is the call graph for this function:

◆ drawText()

void FotoBox::FotoBox::drawText ( const QString &  i_text)
private

Draw text on the QPixmap.

See also
m_photo
Parameters
i_texttext to write

Definition at line 260 of file fotobox.cpp.

261 {
262  //painter begins painting the paint device immediately!
263  QPainter painter(&m_photo);
264 
265  //set color and font
266  painter.setPen(QPen(PreferenceProvider::instance().backgroundColor()));
267 
268  //calculate best font size
269  QFont font = painter.font();
270  const auto size = calculateFontSize(m_photo.rect().width(), painter.fontMetrics().boundingRect(i_text).width());
271  font.setPointSizeF(font.pointSizeF() * size);
272  painter.setFont(font);
273 
274  //draw text on image
275  painter.drawText(m_photo.rect(), Qt::AlignCenter, i_text);
276 
277  m_ui->lblPhoto->setPixmap(m_photo);
278 }
QPixmap m_photo
Definition: fotobox.h:157
static auto calculateFontSize(double i_width, double i_widthFont) -> double
calculate "maximum" fitting font size
Definition: fotobox.cpp:280

References FotoBox::PreferenceProvider::instance().

+ Here is the call graph for this function:

◆ keyPressEvent()

void FotoBox::FotoBox::keyPressEvent ( QKeyEvent *  event)
overrideprivate

filter key press events

Enter -> take a photo / Escape -> quit application

Parameters
eventQKeyEvent

Definition at line 151 of file fotobox.cpp.

152 {
153  //prevent triggering method too often
154  if (!event->isAutoRepeat()) {
155  //start FotoBox
156  if (std::any_of(m_triggerKey.cbegin(), m_triggerKey.cend(), [&](const Qt::Key i_key) -> bool { return event->key() == i_key; })) {
157  Q_EMIT start();
158  return;
159  }
160 
161  //preferences dialog
162  if (std::any_of(m_preferenceKey.cbegin(), m_preferenceKey.cend(), [&](const Qt::Key i_key) -> bool { return event->key() == i_key; })) {
164  return;
165  }
166 
167  //quit application
168  if (std::any_of(m_quitKey.cbegin(), m_quitKey.cend(), [&](const Qt::Key i_key) -> bool { return event->key() == i_key; })) {
169  if (event->modifiers() == Qt::ShiftModifier) {
170  QCoreApplication::quit();
171  }
172  m_ui->statusBar->showMessage(tr("To quit the application, please hold down the Shift key while press Escape key."), STATUSBAR_MSG_TIMEOUT);
173  return;
174  }
175  }
176 }
void start()
signal: start FotoBox
void preferenceDialog()
show preference dialog and close dialog
Definition: fotobox.cpp:189
const std::vector< Qt::Key > m_quitKey
Definition: fotobox.h:170
const std::vector< Qt::Key > m_triggerKey
Definition: fotobox.h:164
const std::vector< Qt::Key > m_preferenceKey
Definition: fotobox.h:167

◆ loadPhoto()

void FotoBox::FotoBox::loadPhoto ( const QString &  i_filePath)
private

try to load the photo to QPixmap

Parameters
i_filePathpath to photo

Definition at line 238 of file fotobox.cpp.

239 {
240  //try to load the photo shot by camera
241  if (m_photo.load(i_filePath)) {
242  //resize picture to label size
243  QSize size(m_ui->lblPhoto->width(), m_ui->lblPhoto->height());
244 
245  //show photo in grayscale (monochrome photography)
246  if (PreferenceProvider::instance().grayscale()) {
247  const auto grey = m_photo.toImage().convertToFormat(QImage::Format_Grayscale8);
248  m_photo.convertFromImage(grey);
249  }
250 
251  //scale photo and show it immediately
252  m_photo = m_photo.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
253  m_ui->lblPhoto->setPixmap(m_photo);
254  m_ui->lblPhoto->repaint();
255  } else {
256  m_ui->statusBar->showMessage(tr("Couldn't load the photo."), STATUSBAR_MSG_TIMEOUT);
257  }
258 }

References FotoBox::PreferenceProvider::instance().

+ Here is the call graph for this function:

◆ mouseReleaseEvent()

void FotoBox::FotoBox::mouseReleaseEvent ( QMouseEvent *  event)
overrideprivate

This event handler, for event event, can be reimplemented in a subclass to receive mouse release events for the widget.

no buttons on UI and left click

See also
emit start()
Parameters
eventQMouseEvent

Definition at line 178 of file fotobox.cpp.

179 {
180  //touch support only when no buttons are shown
181  if (!PreferenceProvider::instance().showButtons() && (event->button() == Qt::LeftButton || event->button() == Qt::RightButton)) {
182  Q_EMIT start();
183  return;
184  }
185 
186  QWidget::mouseReleaseEvent(event);
187 }

References FotoBox::PreferenceProvider::instance().

+ Here is the call graph for this function:

◆ operator=() [1/2]

FotoBox& FotoBox::FotoBox::operator= ( const FotoBox other)
delete

FotoBox default copy assignment.

◆ operator=() [2/2]

FotoBox& FotoBox::FotoBox::operator= ( FotoBox &&  other)
delete

FotoBox default move assignment.

◆ photo

void FotoBox::FotoBox::photo ( )
privateslot

trigger camera to shot a photo and try to show it

Definition at line 208 of file fotobox.cpp.

209 {
210  //show label and hide other widgets
211  m_ui->lcdCountdown->hide();
212  QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
213 
214  //remove current photo
215  m_ui->lblPhoto->show();
216  m_ui->lblPhoto->clear();
217  m_ui->lblPhoto->repaint();
218 
219  //take a photo
220  if (m_camera.shootPhoto()) {
221  //load photo
223  } else {
224  m_ui->statusBar->showMessage(tr("Error: Taking a photo isn't working correctly!"), STATUSBAR_MSG_TIMEOUT);
225  }
226 
227  //restart countdown and Buzzer
229  m_countdown.reset();
230  }
231 #if defined(BUZZER_AVAILABLE)
232  if (PreferenceProvider::instance().queryInterval() > 0) {
233  emit startBuzzer();
234  }
235 #endif
236 }
auto currentPhoto() const -> QString
return member
Definition: camera.cpp:48
auto shootPhoto() -> bool
shoot a photo with gphoto2
Definition: camera.cpp:32
auto reset() -> bool
Reset countdown (reset.
Definition: countdown.cpp:88
void loadPhoto(const QString &i_filePath)
try to load the photo to QPixmap
Definition: fotobox.cpp:238

References FotoBox::PreferenceProvider::instance().

+ Here is the call graph for this function:

◆ preferenceDialog

void FotoBox::FotoBox::preferenceDialog ( )
privateslot

show preference dialog and close dialog

Definition at line 189 of file fotobox.cpp.

190 {
191  //Preferences dialog
192  auto *dialog = new Preferences;
193 
194  //restore mouse cursor
195  QApplication::restoreOverrideCursor();
196 
197  //close fotobox and show preferences
198  reject();
199 
200 #if defined(Q_OS_MACOS)
201  //QTBUG-36714: Window can't be closed on Mac OS X after calling showFullScreen()
203 #endif
204 
205  dialog->show();
206 }
void closeFullscreenWindowOnMac()
Is used as a workaround for macOS to close a fullscreen window.
Definition: fotoboxmac.mm:16

◆ start

void FotoBox::FotoBox::start ( )
signal

signal: start FotoBox

◆ startBuzzer

void FotoBox::FotoBox::startBuzzer ( )
signal

signal: start query pin with Buzzer class

Member Data Documentation

◆ COMPARE

constexpr double FotoBox::FotoBox::COMPARE = 1.25
staticconstexprprivate

1.25

Definition at line 139 of file fotobox.h.

◆ m_buzzer

Buzzer FotoBox::FotoBox::m_buzzer
private

buzzer using pigpio library

Definition at line 151 of file fotobox.h.

◆ m_camera

Camera FotoBox::FotoBox::m_camera
private

Camera (shot photo)

Definition at line 154 of file fotobox.h.

◆ m_countdown

Countdown FotoBox::FotoBox::m_countdown
private

Countdown

Definition at line 145 of file fotobox.h.

◆ m_photo

QPixmap FotoBox::FotoBox::m_photo
private

store / load the photo

Definition at line 157 of file fotobox.h.

◆ m_photoDir

const QString FotoBox::FotoBox::m_photoDir
private

photo directory

Definition at line 160 of file fotobox.h.

◆ m_preferenceKey

const std::vector<Qt::Key> FotoBox::FotoBox::m_preferenceKey {Qt::Key_P, Qt::Key_S, Qt::Key_E}
private

keyboard shortcut to go back to preference dialog

Definition at line 167 of file fotobox.h.

◆ m_quitKey

const std::vector<Qt::Key> FotoBox::FotoBox::m_quitKey {Qt::Key_Escape, Qt::Key_Q}
private

keyboard shortcut to quit the application

Definition at line 170 of file fotobox.h.

◆ m_triggerKey

const std::vector<Qt::Key> FotoBox::FotoBox::m_triggerKey {Qt::Key_N, Qt::Key_Return, Qt::Key_Enter, Qt::Key_PageDown, Qt::Key_PageUp, Qt::Key_Left, Qt::Key_Right, Qt::Key_Up, Qt::Key_Down, Qt::Key_Space, Qt::Key_Backspace}
private

keyboard shortcut to start FotoBox

Definition at line 164 of file fotobox.h.

◆ m_ui

Ui::FotoBoxDialog* FotoBox::FotoBox::m_ui
private

User Interface

Definition at line 142 of file fotobox.h.

◆ m_workerThread

QThread FotoBox::FotoBox::m_workerThread
private

handle Buzzer thread (Raspberry Pi GPIO)

Definition at line 148 of file fotobox.h.

◆ STATUSBAR_MSG_TIMEOUT

constexpr int FotoBox::FotoBox::STATUSBAR_MSG_TIMEOUT = 8000
staticconstexprprivate

status bar timout value

Definition at line 136 of file fotobox.h.


The documentation for this class was generated from the following files: