1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2004-10-05
7  * Description : a tool bar for slideshow
8  *
9  * Copyright (C) 2004-2005 by Renchi Raju <renchi dot raju at gmail dot com>
10  * Copyright (C) 2006-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
11  * Copyright (C) 2019-2020 by Minh Nghia Duong <minhnghiaduong997 at gmail dot com>
12  * Copyright (C)      2021 by Phuoc Khanh Le <phuockhanhnk94 at gmail dot com>
13  *
14  * This program is free software; you can redistribute it
15  * and/or modify it under the terms of the GNU General
16  * Public License as published by the Free Software Foundation;
17  * either version 2, or (at your option)
18  * any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * ============================================================ */
26 
27 #include "slidetoolbar.h"
28 
29 // Qt includes
30 
31 #include <QApplication>
32 #include <QActionGroup>
33 #include <QToolButton>
34 #include <QPixmap>
35 #include <QScreen>
36 #include <QMenu>
37 #include <QInputDialog>
38 #include <QMessageBox>
39 
40 // KDE includes
41 
42 #include <klocalizedstring.h>
43 
44 // Local includes
45 
46 #include "dpluginaboutdlg.h"
47 #include "digikam_debug.h"
48 #include "setupslideshow_dialog.h"
49 
50 namespace DigikamGenericSlideShowPlugin
51 {
52 
53 class Q_DECL_HIDDEN SlideToolBar::Private
54 {
55 public:
56 
Private()57     explicit Private()
58       : playBtn         (nullptr),
59         prevBtn         (nullptr),
60         nextBtn         (nullptr),
61         stopBtn         (nullptr),
62         delayBtn        (nullptr),
63         deleteBtn       (nullptr),
64         setupBtn        (nullptr),
65         screenSelectBtn (nullptr),
66         currentlyPause  (false),
67         configDialog    (nullptr),
68         settings        (nullptr)
69     {
70     }
71 
72     QToolButton*          playBtn;
73     QToolButton*          prevBtn;
74     QToolButton*          nextBtn;
75     QToolButton*          stopBtn;
76     QToolButton*          delayBtn;
77     QToolButton*          deleteBtn;
78     QToolButton*          setupBtn;
79     QToolButton*          screenSelectBtn;
80 
81     bool                  currentlyPause;
82 
83     SetupSlideShowDialog* configDialog;
84     SlideShowSettings*    settings;
85 };
86 
SlideToolBar(SlideShowSettings * const settings,QWidget * const parent)87 SlideToolBar::SlideToolBar(SlideShowSettings* const settings, QWidget* const parent)
88     : DHBox(parent),
89       d    (new Private)
90 {
91     setMouseTracking(true);
92     setContentsMargins(QMargins());
93 
94     d->settings       = settings;
95 
96     d->playBtn        = new QToolButton(this);
97     d->prevBtn        = new QToolButton(this);
98     d->nextBtn        = new QToolButton(this);
99     d->stopBtn        = new QToolButton(this);
100     d->delayBtn       = new QToolButton(this);
101     d->deleteBtn      = new QToolButton(this);
102     d->setupBtn       = new QToolButton(this);
103 
104     d->configDialog   = new SetupSlideShowDialog(d->settings);
105 
106     d->playBtn->setCheckable(true);
107     d->playBtn->setChecked(!d->settings->autoPlayEnabled);
108     d->playBtn->setFocusPolicy(Qt::NoFocus);
109     d->prevBtn->setFocusPolicy(Qt::NoFocus);
110     d->nextBtn->setFocusPolicy(Qt::NoFocus);
111     d->stopBtn->setFocusPolicy(Qt::NoFocus);
112     d->delayBtn->setFocusPolicy(Qt::NoFocus);
113     d->deleteBtn->setFocusPolicy(Qt::NoFocus);
114     d->setupBtn->setFocusPolicy(Qt::NoFocus);
115 
116     QSize s(32, 32);
117     d->playBtn->setIconSize(s);
118     d->prevBtn->setIconSize(s);
119     d->nextBtn->setIconSize(s);
120     d->stopBtn->setIconSize(s);
121     d->delayBtn->setIconSize(s);
122     d->deleteBtn->setIconSize(s);
123     d->setupBtn->setIconSize(s);
124 
125     QString iconString = d->settings->autoPlayEnabled ? QLatin1String("media-playback-pause")
126                                                       : QLatin1String("media-playback-start");
127     d->playBtn->setIcon(QIcon::fromTheme(iconString));
128     d->prevBtn->setIcon(QIcon::fromTheme(QLatin1String("media-skip-backward")));
129     d->nextBtn->setIcon(QIcon::fromTheme(QLatin1String("media-skip-forward")));
130     d->stopBtn->setIcon(QIcon::fromTheme(QLatin1String("media-playback-stop")));
131     d->delayBtn->setIcon(QIcon::fromTheme(QLatin1String("appointment-new")));
132     d->deleteBtn->setIcon(QIcon::fromTheme(QLatin1String("user-trash")));
133     d->setupBtn->setIcon(QIcon::fromTheme(QLatin1String("systemsettings")));
134 
135     int num = qApp->screens().count();
136 
137     if (num > 1)
138     {
139         d->screenSelectBtn        = new QToolButton(this);
140         QMenu* const screenMenu   = new QMenu(d->screenSelectBtn);
141         d->screenSelectBtn->setToolTip(i18n("Switch Screen"));
142         d->screenSelectBtn->setIconSize(s);
143         d->screenSelectBtn->setIcon(QIcon::fromTheme(QLatin1String("video-display")));
144         d->screenSelectBtn->setMenu(screenMenu);
145         d->screenSelectBtn->setPopupMode(QToolButton::InstantPopup);
146         d->screenSelectBtn->setFocusPolicy(Qt::NoFocus);
147 
148         QActionGroup* const group = new QActionGroup(screenMenu);
149         group->setExclusive(true);
150 
151         for (int i = 0 ; i < num ; ++i)
152         {
153             QString model      = qApp->screens().at(i)->model();
154             QAction* const act = screenMenu->addAction(i18nc("%1 is the screen number (0, 1, ...)", "Screen %1", i) +
155                                                        QString::fromUtf8(" (%1)").arg(model.left(model.length() - 1)));
156             act->setData(QVariant::fromValue(i));
157             act->setCheckable(true);
158             group->addAction(act);
159 
160             if (i == d->settings->slideScreen)
161             {
162                act->setChecked(true);
163             }
164         }
165 
166         connect(screenMenu, SIGNAL(triggered(QAction*)),
167                 this, SLOT(slotScreenSelected(QAction*)));
168     }
169 
170     connect(d->playBtn, SIGNAL(toggled(bool)),
171             this, SLOT(slotPlayBtnToggled()));
172 
173     connect(d->nextBtn, SIGNAL(clicked()),
174             this, SLOT(slotNexPrevClicked()));
175 
176     connect(d->prevBtn, SIGNAL(clicked()),
177             this, SLOT(slotNexPrevClicked()));
178 
179     connect(d->nextBtn, SIGNAL(clicked()),
180             this, SIGNAL(signalNext()));
181 
182     connect(d->prevBtn, SIGNAL(clicked()),
183             this, SIGNAL(signalPrev()));
184 
185     connect(d->stopBtn, SIGNAL(clicked()),
186             this, SIGNAL(signalClose()));
187 
188     connect(d->delayBtn, SIGNAL(clicked()),
189             this, SLOT(slotChangeDelayButtonPressed()));
190 
191     connect(d->deleteBtn, SIGNAL(clicked()),
192             this, SLOT(slotRemoveImage()));
193 
194     connect(d->setupBtn, SIGNAL(clicked()),
195             this, SLOT(slotMenuSlideShowConfiguration()));
196 
197     connect(d->configDialog, SIGNAL(finished(int)),
198             this, SIGNAL(signalUpdateSettings()));
199 
200     connect(d->configDialog, SIGNAL(finished(int)),
201             this, SLOT(slotConfigurationAccepted()));
202 }
203 
~SlideToolBar()204 SlideToolBar::~SlideToolBar()
205 {
206     delete d->configDialog;
207     delete d;
208 }
209 
isPaused() const210 bool SlideToolBar::isPaused() const
211 {
212     return d->playBtn->isChecked();
213 }
214 
pause(bool val)215 void SlideToolBar::pause(bool val)
216 {
217     if (val == isPaused())
218     {
219         return;
220     }
221 
222     d->playBtn->setChecked(val);
223     slotPlayBtnToggled();
224 }
225 
setEnabledPlay(bool val)226 void SlideToolBar::setEnabledPlay(bool val)
227 {
228     d->playBtn->setEnabled(val);
229 }
230 
setEnabledNext(bool val)231 void SlideToolBar::setEnabledNext(bool val)
232 {
233     d->nextBtn->setEnabled(val);
234 }
235 
setEnabledPrev(bool val)236 void SlideToolBar::setEnabledPrev(bool val)
237 {
238     d->prevBtn->setEnabled(val);
239 }
240 
closeConfigurationDialog()241 void SlideToolBar::closeConfigurationDialog()
242 {
243     if (d->configDialog->isVisible())
244     {
245         d->configDialog->reject();
246     }
247 }
248 
slotPlayBtnToggled()249 void SlideToolBar::slotPlayBtnToggled()
250 {
251     if (d->playBtn->isChecked())
252     {
253         d->playBtn->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start")));
254 
255         emit signalPause();
256     }
257     else
258     {
259         d->playBtn->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
260 
261         emit signalPlay();
262     }
263 }
264 
slotChangeDelayButtonPressed()265 void SlideToolBar::slotChangeDelayButtonPressed()
266 {
267     bool ok;
268     int delay    = d->settings->delay;
269     bool running = (!isPaused() && d->playBtn->isEnabled());
270 
271     if (running)
272     {
273         d->playBtn->animateClick();
274     }
275 
276     delay = QInputDialog::getInt(this, i18n("Specify delay for slide show"),
277                                        i18n("Delay:"), delay, 1, 3600, 1, &ok);
278 
279     if (ok)
280     {
281         d->settings->delay = delay;
282     }
283 
284     if (running)
285     {
286         d->playBtn->animateClick();
287     }
288 }
289 
slotNexPrevClicked()290 void SlideToolBar::slotNexPrevClicked()
291 {
292     if (!d->playBtn->isChecked())
293     {
294         d->playBtn->setChecked(true);
295         d->playBtn->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start")));
296 
297         emit signalPause();
298     }
299 }
300 
slotMenuSlideShowConfiguration()301 void SlideToolBar::slotMenuSlideShowConfiguration()
302 {
303     if (d->configDialog->isVisible())
304     {
305         d->configDialog->reject();
306 
307         return;
308     }
309 
310     d->currentlyPause = isPaused();
311 
312     if (!d->currentlyPause && d->playBtn->isEnabled())
313     {
314         d->playBtn->animateClick();
315     }
316 
317     d->configDialog->show();
318 }
319 
slotConfigurationAccepted()320 void SlideToolBar::slotConfigurationAccepted()
321 {
322     if (!d->currentlyPause && d->playBtn->isEnabled())
323     {
324         d->playBtn->animateClick();
325     }
326 }
327 
keyPressEvent(QKeyEvent * e)328 void SlideToolBar::keyPressEvent(QKeyEvent* e)
329 {
330     switch (e->key())
331     {
332         case (Qt::Key_F1):
333         {
334             d->currentlyPause = isPaused();
335 
336             if (!d->currentlyPause && d->playBtn->isEnabled())
337             {
338                 d->playBtn->animateClick();
339             }
340 
341             QPointer<DPluginAboutDlg> help = new DPluginAboutDlg(d->settings->plugin);
342             help->exec();
343             delete help;
344 
345             if (!d->currentlyPause && d->playBtn->isEnabled())
346             {
347                 d->playBtn->animateClick();
348             }
349 
350             break;
351         }
352 
353         case (Qt::Key_F2):
354         {
355             slotMenuSlideShowConfiguration();
356             break;
357         }
358 
359         case (Qt::Key_Space):
360         {
361             if (d->playBtn->isEnabled())
362             {
363                 d->playBtn->animateClick();
364             }
365 
366             break;
367         }
368 
369         case (Qt::Key_Left):
370         case (Qt::Key_Up):
371         case (Qt::Key_PageUp):
372         {
373             if (d->prevBtn->isEnabled())
374             {
375                 d->prevBtn->animateClick();
376             }
377 
378             break;
379         }
380 
381         case (Qt::Key_Right):
382         case (Qt::Key_Down):
383         case (Qt::Key_PageDown):
384         {
385             if (d->nextBtn->isEnabled())
386             {
387                 d->nextBtn->animateClick();
388             }
389 
390             break;
391         }
392 
393         case (Qt::Key_Escape):
394         {
395             if (d->stopBtn->isEnabled())
396             {
397                 d->stopBtn->animateClick();
398             }
399 
400             break;
401         }
402 
403         default:
404         {
405             break;
406         }
407     }
408 
409     e->accept();
410 }
411 
slotScreenSelected(QAction * act)412 void SlideToolBar::slotScreenSelected(QAction* act)
413 {
414     if (!act || (act->data().type() != QVariant::Int))
415     {
416         return;
417     }
418 
419     emit signalScreenSelected(act->data().toInt());
420 }
421 
slotRemoveImage()422 void SlideToolBar::slotRemoveImage()
423 {
424     bool running = (!isPaused() && d->playBtn->isEnabled());
425 
426     if (running)
427     {
428         d->playBtn->animateClick();
429     }
430 
431     QPointer<QMessageBox> msgBox = new QMessageBox(QMessageBox::Question,
432              i18n("Delete image"),
433              i18n("Do you want to move this image to the trash?"),
434              QMessageBox::Yes | QMessageBox::No, this);
435 
436     msgBox->setDefaultButton(QMessageBox::Yes);
437 
438     int ret = msgBox->exec();
439     delete msgBox;
440 
441     if (ret == QMessageBox::Yes)
442     {
443         emit signalRemoveImageFromList();
444     }
445 
446     if (running)
447     {
448         d->playBtn->animateClick();
449     }
450 }
451 
452 } // namespace DigikamGenericSlideShowPlugin
453