1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2003-02-16
7  * Description : a presentation tool.
8  *
9  * Copyright (C) 2006-2009 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
10  * Copyright (C)      2009 by Andi Clemens <andi dot clemens at googlemail dot com>
11  * Copyright (C) 2003-2005 by Renchi Raju <renchi dot raju at gmail dot com>
12  * Copyright (C) 2012-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
13  * Copyright (C)      2021 by Phuoc Khanh Le <phuockhanhnk94 at gmail dot com>
14  *
15  * This program is free software; you can redistribute it
16  * and/or modify it under the terms of the GNU General
17  * Public License as published by the Free Software Foundation;
18  * either version 2, or (at your option) 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 "presentationwidget.h"
28 
29 // C++ includes
30 
31 #include <cmath>
32 #include <cstdlib>
33 #include <ctime>
34 
35 // Qt includes
36 
37 #include <QCursor>
38 #include <QFont>
39 #include <QKeyEvent>
40 #include <QMouseEvent>
41 #include <QPainter>
42 #include <QPainterPath>
43 #include <QPixmap>
44 #include <QPolygon>
45 #include <QTimer>
46 #include <QWheelEvent>
47 #include <QApplication>
48 #include <QScreen>
49 #include <QWindow>
50 
51 #include <QDebug>
52 
53 // KDE includes
54 
55 #include <klocalizedstring.h>
56 
57 // Local includes
58 
59 #include "digikam_config.h"
60 #include "presentationcontainer.h"
61 #include "presentationctrlwidget.h"
62 #include "presentationloader.h"
63 #include "presentation_mainpage.h"
64 
65 #ifdef HAVE_MEDIAPLAYER
66 #   include "presentationaudiowidget.h"
67 #   include "slidevideo.h"
68 #endif
69 
70 using namespace Digikam;
71 
72 namespace DigikamGenericPresentationPlugin
73 {
74 
75 class Q_DECL_HIDDEN PresentationWidget::Private
76 {
77 
78 public:
79 
Private()80     explicit Private()
81       : sharedData      (nullptr),
82         imageLoader     (nullptr),
83 
84 #ifdef HAVE_MEDIAPLAYER
85 
86         playbackWidget  (nullptr),
87         videoView       (nullptr),
88 
89 #endif
90 
91         timer           (nullptr),
92         fileIndex       (0),
93         effect          (nullptr),
94         effectRunning   (false),
95         x               (0),
96         y               (0),
97         w               (0),
98         h               (0),
99         dx              (0),
100         dy              (0),
101         ix              (0),
102         iy              (0),
103         i               (0),
104         j               (0),
105         subType         (0),
106         x0              (0),
107         y0              (0),
108         x1              (0),
109         y1              (0),
110         wait            (0),
111         fx              (0),
112         fy              (0),
113         alpha           (0),
114         fd              (0),
115         intArray        (nullptr),
116         pdone           (0),
117         pixelMatrix     (nullptr),
118         slideCtrlWidget (nullptr),
119         mouseMoveTimer  (nullptr),
120         deskX           (0),
121         deskY           (0),
122         deskWidth       (0),
123         deskHeight      (0)
124     {
125     }
126 
127     PresentationContainer*      sharedData;
128 
129     // -------------------------
130 
131     QMap<QString, EffectMethod> Effects;
132 
133     PresentationLoader*         imageLoader;
134     QPixmap                     currImage;
135 
136 #ifdef HAVE_MEDIAPLAYER
137 
138     PresentationAudioWidget*    playbackWidget;
139     SlideVideo*                 videoView;
140 
141 #endif
142 
143     QTimer*                     timer;
144     int                         fileIndex;
145 
146     EffectMethod                effect;
147     bool                        effectRunning;
148     QString                     effectName;
149 
150     /// values for state of various effects
151     int                         x;
152     int                         y;
153     int                         w;
154     int                         h;
155     int                         dx;
156     int                         dy;
157     int                         ix;
158     int                         iy;
159     int                         i;
160     int                         j;
161     int                         subType;
162     int                         x0;
163     int                         y0;
164     int                         x1;
165     int                         y1;
166     int                         wait;
167     double                      fx;
168     double                      fy;
169     double                      alpha;
170     double                      fd;
171     int*                        intArray;
172     bool                        pdone;
173     bool**                      pixelMatrix;
174 
175     /// static
176     QPolygon                    pa;
177 
178     PresentationCtrlWidget*     slideCtrlWidget;
179     QTimer*                     mouseMoveTimer;
180 
181     int                         deskX;
182     int                         deskY;
183     int                         deskWidth;
184     int                         deskHeight;
185 };
186 
PresentationWidget(PresentationContainer * const sharedData)187 PresentationWidget::PresentationWidget(PresentationContainer* const sharedData)
188     : QWidget(),
189       d      (new Private)
190 {
191     setAttribute(Qt::WA_DeleteOnClose);
192     setContextMenuPolicy(Qt::PreventContextMenu);
193 
194 #ifdef Q_OS_WIN
195 
196     setWindowFlags(Qt::Popup               |
197                    Qt::FramelessWindowHint |
198                    Qt::WindowStaysOnTopHint);
199 
200 #else
201 
202     setWindowState(windowState() | Qt::WindowFullScreen);
203 
204 #endif
205 
206     QScreen* screen = qApp->primaryScreen();
207 
208     if (QWidget* const widget = qApp->activeWindow())
209     {
210         if (QWindow* const window = widget->windowHandle())
211         {
212             screen = window->screen();
213         }
214     }
215 
216     QRect deskRect  = screen->geometry();
217     d->deskX        = deskRect.x();
218     d->deskY        = deskRect.y();
219     d->deskWidth    = deskRect.width();
220     d->deskHeight   = deskRect.height();
221 
222     move(d->deskX, d->deskY);
223     resize(d->deskWidth, d->deskHeight);
224 
225     d->sharedData   = sharedData;
226 
227     d->slideCtrlWidget = new PresentationCtrlWidget(this, d->sharedData);
228     d->slideCtrlWidget->hide();
229 
230     int w = d->slideCtrlWidget->width() - 1;
231     d->slideCtrlWidget->move(d->deskX + d->deskWidth - w, d->deskY);
232 
233     if (!d->sharedData->loop)
234     {
235         d->slideCtrlWidget->setEnabledPrev(false);
236     }
237 
238     connect(d->slideCtrlWidget, SIGNAL(signalPause()),
239             this, SLOT(slotPause()));
240 
241     connect(d->slideCtrlWidget, SIGNAL(signalPlay()),
242             this, SLOT(slotPlay()));
243 
244     connect(d->slideCtrlWidget, SIGNAL(signalNext()),
245             this, SLOT(slotNext()));
246 
247     connect(d->slideCtrlWidget, SIGNAL(signalPrev()),
248             this, SLOT(slotPrev()));
249 
250     connect(d->slideCtrlWidget, SIGNAL(signalClose()),
251             this, SLOT(slotClose()));
252 
253     connect(d->slideCtrlWidget, SIGNAL(signalRemoveImageFromList()),
254             this, SLOT(slotRemoveImageFromList()));
255 
256 #ifdef HAVE_MEDIAPLAYER
257 
258     // -- playback widget -------------------------------
259 
260     d->playbackWidget = new PresentationAudioWidget(this, d->sharedData->soundtrackUrls, d->sharedData);
261     d->playbackWidget->hide();
262     d->playbackWidget->move(d->deskX, d->deskY);
263 
264     // -- video preview ---------------------------------
265 
266     d->videoView = new SlideVideo(this);
267 
268     // TODO: pass mouse events from d->videoView to this ?
269     //d->videoView->installEventFilter(this);
270 
271     connect(d->videoView, SIGNAL(signalVideoLoaded(bool)),
272             this, SLOT(slotVideoLoaded(bool)));
273 
274     connect(d->videoView, SIGNAL(signalVideoFinished()),
275             this, SLOT(slotVideoFinished()));
276 
277     d->videoView->hide();
278     d->videoView->resize(d->deskWidth, d->deskHeight);
279 
280 #endif
281 
282     // ---------------------------------------------------------------
283 
284     d->fileIndex     = -1; // start with -1
285     d->effect        = nullptr;
286     d->effectRunning = false;
287     d->intArray      = nullptr;
288     m_endOfShow      = false;
289     m_simplyShow     = false;
290     m_startPainter   = false;
291     m_firstPainter   = true;
292     d->timer         = new QTimer(this);
293 
294     connect(d->timer, SIGNAL(timeout()),
295             this, SLOT(slotTimeOut()));
296 
297     d->pa            = QPolygon(4);
298     m_buffer         = QPixmap(size());
299     m_buffer.fill(Qt::black);
300 
301     d->imageLoader   = new PresentationLoader(d->sharedData, width(), height(), d->fileIndex);
302 
303     // --------------------------------------------------
304 
305     registerEffects();
306 
307     if (d->sharedData->effectName == QLatin1String("Random"))
308     {
309         d->effect = getRandomEffect();
310     }
311     else
312     {
313         d->effectName = d->sharedData->effectName;
314         d->effect     = d->Effects[d->sharedData->effectName];
315 
316         if (!d->effect)
317         {
318             d->effect     = d->Effects[QLatin1String("None")];
319             d->effectName = QLatin1String("None");
320         }
321     }
322 
323     d->timer->setSingleShot(true);
324 
325     if (d->sharedData->offAutoDelay)
326     {
327         d->timer->stop();
328         slotTimeOut();
329     }
330     else
331     {
332         d->timer->start(500);
333     }
334 
335     // -- hide cursor when not moved --------------------
336 
337     d->mouseMoveTimer = new QTimer(this);
338     d->mouseMoveTimer->setSingleShot(true);
339 
340     connect(d->mouseMoveTimer, SIGNAL(timeout()),
341             this, SLOT(slotMouseMoveTimeOut()));
342 
343     setMouseTracking(true);
344     slotMouseMoveTimeOut();
345 
346 #ifdef HAVE_MEDIAPLAYER
347 
348     if (d->sharedData->soundtrackPlay)
349     {
350         d->playbackWidget->slotPlay();
351     }
352 
353 #endif
354 
355 }
356 
~PresentationWidget()357 PresentationWidget::~PresentationWidget()
358 {
359 
360 #ifdef HAVE_MEDIAPLAYER
361 
362     d->playbackWidget->slotStop();
363 
364 #endif
365 
366     d->timer->stop();
367     d->mouseMoveTimer->stop();
368 
369     if (d->intArray)
370     {
371         delete [] d->intArray;
372     }
373 
374     delete d->imageLoader;
375     delete d;
376 }
377 
readSettings()378 void PresentationWidget::readSettings()
379 {
380 }
381 
loadNextImage()382 void PresentationWidget::loadNextImage()
383 {
384     if (!d->currImage.isNull())
385     {
386         m_firstPainter = false;
387         m_buffer       = d->currImage;
388     }
389     else
390     {
391         m_buffer = QPixmap(size());
392         m_buffer.fill(Qt::black);
393     }
394 
395     d->fileIndex++;
396 
397     d->imageLoader->next();
398     int num = d->sharedData->urlList.count();
399 
400     if (d->fileIndex >= num)
401     {
402         if (d->sharedData->loop)
403         {
404             d->fileIndex = 0;
405         }
406         else
407         {
408             d->currImage = QPixmap(0, 0);
409             d->fileIndex = num - 1;
410             return;
411         }
412     }
413 
414     if (!d->sharedData->loop)
415     {
416         d->slideCtrlWidget->setEnabledPrev(d->fileIndex > 0);
417         d->slideCtrlWidget->setEnabledNext(d->fileIndex < num - 1);
418     }
419 
420     QImage img        = d->imageLoader->getCurrent();
421 
422     QPixmap newPixmap = QPixmap::fromImage(img);
423     QPixmap pixmap(width(), height());
424     pixmap.fill(Qt::black);
425     QPainter p(&pixmap);
426 
427     p.drawPixmap((width() - newPixmap.width()) / 2,
428                  (height() - newPixmap.height()) / 2, newPixmap,
429                  0, 0, newPixmap.width(), newPixmap.height());
430 
431     d->currImage = pixmap;
432 
433     if (img.isNull())
434     {
435 
436 #ifdef HAVE_MEDIAPLAYER
437 
438         d->videoView->setCurrentUrl(d->imageLoader->currPath());
439 
440 #endif
441 
442     }
443 }
444 
loadPrevImage()445 void PresentationWidget::loadPrevImage()
446 {
447     d->fileIndex--;
448     d->imageLoader->prev();
449 
450     int num = d->sharedData->urlList.count();
451 
452     if (d->fileIndex < 0)
453     {
454         if (d->sharedData->loop)
455         {
456             d->fileIndex = num - 1;
457         }
458         else
459         {
460             d->fileIndex = -1; // set this to -1.
461             return;
462         }
463     }
464 
465     if (!d->sharedData->loop)
466     {
467         d->slideCtrlWidget->setEnabledPrev(d->fileIndex > 0);
468         d->slideCtrlWidget->setEnabledNext(d->fileIndex < num - 1);
469     }
470 
471     QImage img = d->imageLoader->getCurrent();
472 
473     QPixmap newPixmap = QPixmap::fromImage(img);
474     QPixmap pixmap(width(), height());
475     pixmap.fill(Qt::black);
476     QPainter p(&pixmap);
477 
478     p.drawPixmap((width()  - newPixmap.width())  / 2,
479                  (height() - newPixmap.height()) / 2, newPixmap,
480                  0, 0, newPixmap.width(), newPixmap.height());
481 
482     d->currImage = pixmap;
483 
484     if (img.isNull())
485     {
486 
487 #ifdef HAVE_MEDIAPLAYER
488 
489         d->videoView->setCurrentUrl(d->imageLoader->currPath());
490 
491 #endif
492 
493     }
494 }
495 
printFilename()496 void PresentationWidget::printFilename()
497 {
498     if (d->currImage.isNull())
499     {
500         return;
501     }
502 
503     QPainter p;
504 
505     p.begin(&d->currImage);
506     p.setPen(Qt::black);
507 
508     for (int x = 9 ; x <= 11 ; ++x)
509     {
510         for (int y = 31 ; y >= 29 ; --y)
511         {
512             p.drawText(x, height() - y, d->imageLoader->currFileName());
513         }
514     }
515 
516     p.setPen(QColor(Qt::white));
517     p.drawText(10, height() - 30, d->imageLoader->currFileName());
518 }
519 
printComments()520 void PresentationWidget::printComments()
521 {
522     if (d->currImage.isNull())
523     {
524         return;
525     }
526 
527     DItemInfo info(d->sharedData->iface->itemInfo(d->imageLoader->currPath()));
528     QString comments = info.comment();
529 
530     int yPos = 30; // Text Y coordinate
531 
532     if (d->sharedData->printFileName)
533     {
534         yPos = 50;
535     }
536 
537     QStringList commentsByLines;
538 
539     uint commentsIndex = 0; // Comments QString index
540 
541     while (commentsIndex < (uint)comments.length())
542     {
543         QString newLine;
544         bool breakLine = false; // End Of Line found
545         uint currIndex; //  Comments QString current index
546 
547         // Check minimal lines dimension
548 
549         uint commentsLinesLengthLocal = d->sharedData->commentsLinesLength;
550 
551         for (currIndex = commentsIndex ; (currIndex < (uint)comments.length()) && !breakLine ; ++currIndex)
552         {
553             if ((comments[currIndex] == QLatin1Char('\n')) || comments[currIndex].isSpace())
554             {
555                 breakLine = true;
556             }
557         }
558 
559         if (commentsLinesLengthLocal <= (currIndex - commentsIndex))
560         {
561             commentsLinesLengthLocal = (currIndex - commentsIndex);
562         }
563 
564         breakLine = false;
565 
566         for (currIndex = commentsIndex ; ((currIndex <= (commentsIndex + commentsLinesLengthLocal)) &&
567              (currIndex < (uint)comments.length()) && !breakLine) ; ++currIndex)
568         {
569             breakLine = (comments[currIndex] == QLatin1Char('\n')) ? true : false;
570 
571             if (breakLine)
572             {
573                 newLine.append(QLatin1Char(' '));
574             }
575             else
576             {
577                 newLine.append(comments[currIndex]);
578             }
579         }
580 
581         commentsIndex = currIndex; // The line is ended
582 
583         if (commentsIndex != (uint)comments.length())
584         {
585             while (!newLine.endsWith(QLatin1Char(' ')))
586             {
587                 newLine.truncate(newLine.length() - 1);
588                 commentsIndex--;
589             }
590         }
591 
592         commentsByLines.prepend(newLine.trimmed());
593     }
594 
595     QPainter p;
596 
597     p.begin(&d->currImage);
598     p.setFont(*d->sharedData->captionFont);
599 
600     for (int lineNumber = 0 ; lineNumber < (int)commentsByLines.count() ; ++lineNumber)
601     {
602         p.setPen(QColor(d->sharedData->commentsBgColor));
603 
604         // coefficient 1.5 is used to maintain distance between different lines
605 
606         for (int x = 9 ; x <= 11 ; ++x)
607         {
608             for (int y = (int)(yPos + lineNumber * 1.5 * d->sharedData->captionFont->pointSize() + 1) ;
609                  y >= (int)(yPos + lineNumber * 1.5 * d->sharedData->captionFont->pointSize() - 1) ; --y)
610             {
611                 p.drawText(x, height() - y, commentsByLines[lineNumber]);
612             }
613         }
614 
615         p.setPen(QColor(d->sharedData->commentsFontColor));
616         p.drawText(10, height() - (int)(lineNumber * 1.5 * d->sharedData->captionFont->pointSize() + yPos),
617                    commentsByLines[lineNumber]);
618     }
619 }
620 
printProgress()621 void PresentationWidget::printProgress()
622 {
623     if (d->currImage.isNull())
624     {
625         return;
626     }
627 
628     QPainter p;
629     p.begin(&d->currImage);
630 
631     QString progress(QString::number(d->fileIndex + 1) + QLatin1Char('/') +
632                                      QString::number(d->sharedData->urlList.count()));
633 
634 #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
635 
636     int stringLength = p.fontMetrics().horizontalAdvance(progress) * progress.length();
637 
638 #else
639 
640     int stringLength = p.fontMetrics().width(progress) * progress.length();
641 
642 #endif
643 
644     p.setPen(QColor(Qt::black));
645 
646     for (int x = 9 ; x <= 11 ; ++x)
647     {
648         for (int y = 21 ; y >= 19 ; --y)
649         {
650             p.drawText(width() - stringLength - x, y, progress);
651         }
652     }
653 
654     p.setPen(QColor(Qt::white));
655     p.drawText(width() - stringLength - 10, 20, progress);
656 }
657 
showEndOfShow()658 void PresentationWidget::showEndOfShow()
659 {
660     m_endOfShow = true;
661     update();
662 
663     d->slideCtrlWidget->setEnabledPlay(false);
664     d->slideCtrlWidget->setEnabledNext(false);
665     d->slideCtrlWidget->setEnabledPrev(false);
666 }
667 
showOverlays()668 void PresentationWidget::showOverlays()
669 {
670     if (d->slideCtrlWidget->isHidden())
671     {
672         int w = d->slideCtrlWidget->width() - 1;
673         d->slideCtrlWidget->move(d->deskX + d->deskWidth - w, d->deskY);
674         d->slideCtrlWidget->show();
675     }
676 
677 #ifdef HAVE_MEDIAPLAYER
678 
679     if (d->playbackWidget->isHidden())
680     {
681         d->playbackWidget->move(d->deskX, d->deskY);
682         d->playbackWidget->show();
683     }
684 
685 #endif
686 
687 }
688 
hideOverlays()689 void PresentationWidget::hideOverlays()
690 {
691     d->slideCtrlWidget->hide();
692 
693 #ifdef HAVE_MEDIAPLAYER
694 
695     d->playbackWidget->hide();
696 
697 #endif
698 
699 }
700 
keyPressEvent(QKeyEvent * event)701 void PresentationWidget::keyPressEvent(QKeyEvent* event)
702 {
703     if (!event)
704     {
705         return;
706     }
707 
708 #ifdef HAVE_MEDIAPLAYER
709 
710     d->playbackWidget->keyPressEvent(event);
711 
712 #endif
713 
714     d->slideCtrlWidget->keyPressEvent(event);
715 }
716 
mousePressEvent(QMouseEvent * e)717 void PresentationWidget::mousePressEvent(QMouseEvent* e)
718 {
719     if (m_endOfShow)
720     {
721         slotClose();
722     }
723 
724     if      (e->button() == Qt::LeftButton)
725     {
726         d->timer->stop();
727         d->slideCtrlWidget->setPaused(!d->sharedData->offAutoDelay);
728         slotNext();
729     }
730     else if ((e->button() == Qt::RightButton) && ((d->fileIndex - 1) >= 0))
731     {
732         d->timer->stop();
733         d->slideCtrlWidget->setPaused(!d->sharedData->offAutoDelay);
734         slotPrev();
735     }
736 }
737 
mouseMoveEvent(QMouseEvent * e)738 void PresentationWidget::mouseMoveEvent(QMouseEvent* e)
739 {
740     setCursor(QCursor(Qt::ArrowCursor));
741     d->mouseMoveTimer->start(1000);
742 
743     if (!d->slideCtrlWidget->canHide()
744 
745 #ifdef HAVE_MEDIAPLAYER
746 
747         || !d->playbackWidget->canHide()
748 
749 #endif
750 
751        )
752     {
753         return;
754     }
755 
756     QPoint pos(e->pos());
757 
758     if ((pos.y() > (d->deskY + 20)) &&
759         (pos.y() < (d->deskY + d->deskHeight - 20 - 1)))
760     {
761         if (!d->slideCtrlWidget->canHide()
762 
763 #ifdef HAVE_MEDIAPLAYER
764 
765             || !d->playbackWidget->canHide()
766 
767 #endif
768 
769            )
770         {
771             return;
772         }
773         else
774         {
775             hideOverlays();
776         }
777 
778         return;
779     }
780 
781     showOverlays();
782 }
783 
wheelEvent(QWheelEvent * e)784 void PresentationWidget::wheelEvent(QWheelEvent* e)
785 {
786     if (!d->sharedData->enableMouseWheel)
787     {
788         return;
789     }
790 
791     if (m_endOfShow)
792     {
793         slotClose();
794     }
795 
796     int delta = e->angleDelta().y();
797 
798     if      (delta < 0)
799     {
800         d->timer->stop();
801         d->slideCtrlWidget->setPaused(true);
802         slotNext();
803     }
804     else if ((delta > 0) && ((d->fileIndex - 1) >= 0))
805     {
806         d->timer->stop();
807         d->slideCtrlWidget->setPaused(true);
808         slotPrev();
809     }
810 }
811 
slotMouseMoveTimeOut()812 void PresentationWidget::slotMouseMoveTimeOut()
813 {
814     QPoint pos(QCursor::pos());
815 
816     if ((pos.y() < (d->deskY + 20))                     ||
817         (pos.y() > (d->deskY + d->deskHeight - 20 - 1)) ||
818         !d->timer->isActive()                           ||
819         d->slideCtrlWidget->underMouse()
820 
821 #ifdef HAVE_MEDIAPLAYER
822 
823         || d->playbackWidget->underMouse()
824 
825 #endif
826 
827        )
828     {
829         return;
830     }
831 
832     setCursor(QCursor(Qt::BlankCursor));
833 }
834 
paintEvent(QPaintEvent *)835 void PresentationWidget::paintEvent(QPaintEvent*)
836 {
837     QPainter p(this);
838 
839     if (m_simplyShow || m_firstPainter)
840     {
841         if (d->sharedData->printFileName)
842         {
843             printFilename();
844         }
845 
846         if (d->sharedData->printProgress)
847         {
848             printProgress();
849         }
850 
851         if (d->sharedData->printFileComments)
852         {
853             printComments();
854         }
855 
856         double ratio   = devicePixelRatioF();
857         QSize fullSize = QSizeF(ratio * width(), ratio * height()).toSize();
858 
859         QPixmap pixmap = d->currImage.scaled(fullSize, Qt::KeepAspectRatio,
860                                                        Qt::SmoothTransformation);
861 
862         p.drawPixmap(0, 0, width(), height(), pixmap,
863                      0, 0, pixmap.width(), pixmap.height());
864 
865         p.end();
866 
867         m_simplyShow = false;
868 
869         return;
870     }
871 
872     if (m_endOfShow)
873     {
874         p.fillRect(0, 0, width(), height(), Qt::black);
875 
876         QFont fn(font());
877         fn.setPointSize(fn.pointSize() + 10);
878         fn.setBold(true);
879 
880         p.setFont(fn);
881         p.setPen(Qt::white);
882         p.drawText(100, 100, i18n("Slideshow Completed"));
883         p.drawText(100, 100 + 10 + fn.pointSize(), i18n("Click to Exit..."));
884 
885         p.end();
886         return;
887     }
888 
889     // If execution reach this line, an effect is running
890 
891     p.drawPixmap(0, 0, m_buffer);
892 }
893 
startPainter()894 void PresentationWidget::startPainter()
895 {
896     m_startPainter = true;
897     repaint();
898 }
899 
slotPause()900 void PresentationWidget::slotPause()
901 {
902     d->timer->stop();
903     showOverlays();
904 }
905 
slotPlay()906 void PresentationWidget::slotPlay()
907 {
908     hideOverlays();
909     slotTimeOut();
910 }
911 
slotPrev()912 void PresentationWidget::slotPrev()
913 {
914     loadPrevImage();
915 
916     if (d->currImage.isNull() || d->sharedData->urlList.isEmpty())
917     {
918         showEndOfShow();
919         return;
920     }
921 
922     d->effectRunning = false;
923 
924     showCurrentImage();
925 }
926 
slotNext()927 void PresentationWidget::slotNext()
928 {
929     loadNextImage();
930 
931     if (d->currImage.isNull() || d->sharedData->urlList.isEmpty())
932     {
933         showEndOfShow();
934         return;
935     }
936 
937     d->effectRunning = false;
938 
939     showCurrentImage();
940 }
941 
slotClose()942 void PresentationWidget::slotClose()
943 {
944     close();
945 }
946 
slotRemoveImageFromList()947 void PresentationWidget::slotRemoveImageFromList()
948 {
949     QUrl url = d->imageLoader->currPath();
950 
951     // Delete or move to trash by url
952 
953     d->sharedData->iface->deleteImage(url);
954 
955     // Delete from list of presentation
956 
957     d->sharedData->urlList.removeOne(url);
958 
959     // Delete from list of mainpage
960 
961     d->sharedData->mainPage->removeImageFromList(url);
962 }
963 
slotVideoLoaded(bool loaded)964 void PresentationWidget::slotVideoLoaded(bool loaded)
965 {
966     if (loaded)
967     {
968 
969 #ifdef HAVE_MEDIAPLAYER
970 
971         slotPause();
972         d->videoView->show();
973 
974 #endif
975 
976     }
977 }
978 
slotVideoFinished()979 void PresentationWidget::slotVideoFinished()
980 {
981 
982 #ifdef HAVE_MEDIAPLAYER
983 
984     d->videoView->hide();
985     slotPlay();
986 
987 #endif
988 
989 }
990 
991 // -- Effects rules --------------------------------------------------------------------------------------------------------
992 
registerEffects()993 void PresentationWidget::registerEffects()
994 {
995     d->Effects.insert(QLatin1String("None"),             &PresentationWidget::effectNone);
996     d->Effects.insert(QLatin1String("Chess Board"),      &PresentationWidget::effectChessboard);
997     d->Effects.insert(QLatin1String("Melt Down"),        &PresentationWidget::effectMeltdown);
998     d->Effects.insert(QLatin1String("Sweep"),            &PresentationWidget::effectSweep);
999     d->Effects.insert(QLatin1String("Mosaic"),           &PresentationWidget::effectMosaic);
1000     d->Effects.insert(QLatin1String("Cubism"),           &PresentationWidget::effectCubism);
1001     d->Effects.insert(QLatin1String("Growing"),          &PresentationWidget::effectGrowing);
1002     d->Effects.insert(QLatin1String("Horizontal Lines"), &PresentationWidget::effectHorizLines);
1003     d->Effects.insert(QLatin1String("Vertical Lines"),   &PresentationWidget::effectVertLines);
1004     d->Effects.insert(QLatin1String("Circle Out"),       &PresentationWidget::effectCircleOut);
1005     d->Effects.insert(QLatin1String("MultiCircle Out"),  &PresentationWidget::effectMultiCircleOut);
1006     d->Effects.insert(QLatin1String("Spiral In"),        &PresentationWidget::effectSpiralIn);
1007     d->Effects.insert(QLatin1String("Blobs"),            &PresentationWidget::effectBlobs);
1008 }
1009 
effectNames()1010 QStringList PresentationWidget::effectNames()
1011 {
1012     QStringList effects;
1013 
1014     effects.append(QLatin1String("None"));
1015     effects.append(QLatin1String("Chess Board"));
1016     effects.append(QLatin1String("Melt Down"));
1017     effects.append(QLatin1String("Sweep"));
1018     effects.append(QLatin1String("Mosaic"));
1019     effects.append(QLatin1String("Cubism"));
1020     effects.append(QLatin1String("Growing"));
1021     effects.append(QLatin1String("Horizontal Lines"));
1022     effects.append(QLatin1String("Vertical Lines"));
1023     effects.append(QLatin1String("Circle Out"));
1024     effects.append(QLatin1String("MultiCircle Out"));
1025     effects.append(QLatin1String("Spiral In"));
1026     effects.append(QLatin1String("Blobs"));
1027     effects.append(QLatin1String("Random"));
1028 
1029     return effects;
1030 }
1031 
effectNamesI18N()1032 QMap<QString, QString> PresentationWidget::effectNamesI18N()
1033 {
1034     QMap<QString, QString> effects;
1035 
1036     effects[QLatin1String("None")]             = i18nc("Filter Effect: No effect",        "None");
1037     effects[QLatin1String("Chess Board")]      = i18nc("Filter Effect: Chess Board",      "Chess Board");
1038     effects[QLatin1String("Melt Down")]        = i18nc("Filter Effect: Melt Down",        "Melt Down");
1039     effects[QLatin1String("Sweep")]            = i18nc("Filter Effect: Sweep",            "Sweep");
1040     effects[QLatin1String("Mosaic")]           = i18nc("Filter Effect: Mosaic",           "Mosaic");
1041     effects[QLatin1String("Cubism")]           = i18nc("Filter Effect: Cubism",           "Cubism");
1042     effects[QLatin1String("Growing")]          = i18nc("Filter Effect: Growing",          "Growing");
1043     effects[QLatin1String("Horizontal Lines")] = i18nc("Filter Effect: Horizontal Lines", "Horizontal Lines");
1044     effects[QLatin1String("Vertical Lines")]   = i18nc("Filter Effect: Vertical Lines",   "Vertical Lines");
1045     effects[QLatin1String("Circle Out")]       = i18nc("Filter Effect: Circle Out",       "Circle Out");
1046     effects[QLatin1String("MultiCircle Out")]  = i18nc("Filter Effect: Multi-Circle Out", "Multi-Circle Out");
1047     effects[QLatin1String("Spiral In")]        = i18nc("Filter Effect: Spiral In",        "Spiral In");
1048     effects[QLatin1String("Blobs")]            = i18nc("Filter Effect: Blobs",            "Blobs");
1049     effects[QLatin1String("Random")]           = i18nc("Filter Effect: Random effect",    "Random");
1050 
1051     return effects;
1052 }
1053 
slotTimeOut()1054 void PresentationWidget::slotTimeOut()
1055 {
1056     if (!d->effect)
1057     {
1058         return;                     // No effect -> bye !
1059     }
1060 
1061     int tmout = -1;
1062 
1063     if (d->effectRunning)           // Effect under progress ?
1064     {
1065         tmout = (this->*d->effect)(false);
1066     }
1067     else
1068     {
1069         loadNextImage();
1070 
1071         if (d->sharedData->offAutoDelay)
1072         {
1073             showCurrentImage();
1074         }
1075         else
1076         {
1077             if (d->currImage.isNull() || d->sharedData->urlList.isEmpty())   // End of slideshow ?
1078             {
1079                 showEndOfShow();
1080                 return;
1081             }
1082 
1083             if (d->sharedData->effectName  == QLatin1String("Random")) // Take a random effect.
1084             {
1085                 if (d->currImage.isNull() || d->sharedData->urlList.isEmpty())   // End of slideshow ?
1086                 {
1087                     showEndOfShow();
1088                     return;
1089                 }
1090             }
1091             d->effectRunning = true;
1092 
1093             tmout = (this->*d->effect)(true);
1094         }
1095     }
1096 
1097     if (tmout <= 0)                 // Effect finished -> delay.
1098     {
1099         tmout            = d->sharedData->delay;
1100         d->effectRunning = false;
1101     }
1102 
1103     if (d->sharedData->offAutoDelay)
1104     {
1105         d->timer->stop();
1106     }
1107     else
1108     {
1109         d->timer->setSingleShot(true);
1110         d->timer->start(tmout);
1111     }
1112 }
1113 
showCurrentImage()1114 void PresentationWidget::showCurrentImage()
1115 {
1116     if (d->currImage.isNull())
1117     {
1118         return;
1119     }
1120 
1121     m_simplyShow = true;
1122 
1123     repaint();
1124 }
1125 
getRandomEffect()1126 PresentationWidget::EffectMethod PresentationWidget::getRandomEffect()
1127 {
1128     QStringList effs = d->Effects.keys();
1129     effs.removeAt(effs.indexOf(QLatin1String("None")));
1130 
1131     int count        = effs.count();
1132     int i            = qrand() % count;
1133     QString key      = effs[i];
1134     d->effectName    = key;
1135 
1136     return d->Effects[key];
1137 }
1138 
effectNone(bool)1139 int PresentationWidget::effectNone(bool /* aInit */)
1140 {
1141     showCurrentImage();
1142 
1143     return -1;
1144 }
1145 
effectChessboard(bool aInit)1146 int PresentationWidget::effectChessboard(bool aInit)
1147 {
1148     if (aInit)
1149     {
1150         d->w    = width();
1151         d->h    = height();
1152         d->dx   = 8;                             // width of one tile
1153         d->dy   = 8;                             // height of one tile
1154         d->j    = (d->w + d->dx - 1) / d->dx;    // number of tiles
1155         d->x    = d->j * d->dx;                  // shrinking x-offset from screen border
1156         d->ix   = 0;                             // growing x-offset from screen border
1157         d->iy   = 0;                             // 0 or d->dy for growing tiling effect
1158         d->y    = (d->j & 1) ? 0 : d->dy;        // 0 or d->dy for shrinking tiling effect
1159         d->wait = 800 / d->j;                    // timeout between effects
1160     }
1161 
1162     if (d->ix >= d->w)
1163     {
1164         showCurrentImage();
1165         return -1;
1166     }
1167 
1168     d->ix += d->dx;
1169     d->x  -= d->dx;
1170     d->iy  = d->iy ? 0 : d->dy;
1171     d->y   = d->y  ? 0 : d->dy;
1172 
1173     QPainter bufferPainter(&m_buffer);
1174     QBrush brush = QBrush(d->currImage);
1175 
1176     for (int y = 0 ; y < d->w ; y += (d->dy << 1))
1177     {
1178         bufferPainter.fillRect(d->ix, y + d->iy, d->dx, d->dy, brush);
1179         bufferPainter.fillRect(d->x,  y + d->y,  d->dx, d->dy, brush);
1180     }
1181 
1182     repaint();
1183 
1184     return d->wait;
1185 }
1186 
effectMeltdown(bool aInit)1187 int PresentationWidget::effectMeltdown(bool aInit)
1188 {
1189     int i;
1190 
1191     if (aInit)
1192     {
1193         delete [] d->intArray;
1194         d->w        = width();
1195         d->h        = height();
1196         d->dx       = 4;
1197         d->dy       = 16;
1198         d->ix       = d->w / d->dx;
1199         d->intArray = new int[d->ix];
1200 
1201         for (i = d->ix - 1 ; i >= 0 ; --i)
1202         {
1203             d->intArray[i] = 0;
1204         }
1205     }
1206 
1207     d->pdone = true;
1208 
1209     int y, x;
1210     QPainter bufferPainter(&m_buffer);
1211 
1212     for (i = 0, x = 0 ; i < d->ix ; ++i, x += d->dx)
1213     {
1214         y = d->intArray[i];
1215 
1216         if (y >= d->h)
1217         {
1218             continue;
1219         }
1220 
1221         d->pdone = false;
1222 
1223         if ((qrand() & 15) < 6)
1224         {
1225             continue;
1226         }
1227 /*
1228         bufferPainter.drawPixmap(x, y + d->dy, m_buffer, x, y, d->dx, d->h - y - d->dy);
1229 */
1230         bufferPainter.drawPixmap(x, y, d->currImage, x, y, d->dx, d->dy);
1231 
1232         d->intArray[i] += d->dy;
1233     }
1234 
1235     bufferPainter.end();
1236 
1237     repaint();
1238 
1239     if (d->pdone)
1240     {
1241         delete [] d->intArray;
1242         d->intArray = nullptr;
1243         showCurrentImage();
1244 
1245         return -1;
1246     }
1247 
1248     return 15;
1249 }
1250 
effectSweep(bool aInit)1251 int PresentationWidget::effectSweep(bool aInit)
1252 {
1253     if (aInit)
1254     {
1255         // subtype: 0=sweep right to left, 1=sweep left to right
1256         //          2=sweep bottom to top, 3=sweep top to bottom
1257 
1258         d->subType = qrand() % 4;
1259         d->w       = width();
1260         d->h       = height();
1261         d->dx      = (d->subType == 1 ? 16 : -16);
1262         d->dy      = (d->subType == 3 ? 16 : -16);
1263         d->x       = (d->subType == 1 ? 0  : d->w);
1264         d->y       = (d->subType == 3 ? 0  : d->h);
1265     }
1266 
1267     if (d->subType == 0 || d->subType == 1)
1268     {
1269         // horizontal sweep
1270 
1271         if (((d->subType == 0) && (d->x < -64)) || ((d->subType == 1) && (d->x > d->w + 64)))
1272         {
1273             showCurrentImage();
1274             return -1;
1275         }
1276 
1277         int w;
1278         int x;
1279         int i;
1280 
1281         for (w = 2, i = 4, x = d->x ; i > 0 ; --i, w <<= 1, x -= d->dx)
1282         {
1283             m_px  = x;
1284             m_py  = 0;
1285             m_psx = w;
1286             m_psy = d->h;
1287 
1288             QPainter bufferPainter(&m_buffer);
1289             bufferPainter.fillRect(m_px, m_py, m_psx, m_psy, QBrush(d->currImage));
1290             bufferPainter.end();
1291 
1292             repaint();
1293         }
1294 
1295         d->x += d->dx;
1296     }
1297     else
1298     {
1299         // vertical sweep
1300 
1301         if (((d->subType == 2) && (d->y < -64)) || ((d->subType == 3) && (d->y > d->h + 64)))
1302         {
1303             showCurrentImage();
1304             return -1;
1305         }
1306 
1307         int h;
1308         int y;
1309         int i;
1310 
1311         for (h = 2, i = 4, y = d->y ; i > 0 ; --i, h <<= 1, y -= d->dy)
1312         {
1313             m_px  = 0;
1314             m_py  = y;
1315             m_psx = d->w;
1316             m_psy = h;
1317 
1318             QPainter bufferPainter(&m_buffer);
1319             bufferPainter.fillRect(m_px, m_py, m_psx, m_psy, QBrush(d->currImage));
1320             bufferPainter.end();
1321 
1322             repaint();
1323         }
1324 
1325         d->y += d->dy;
1326     }
1327 
1328     return 20;
1329 }
1330 
effectMosaic(bool aInit)1331 int PresentationWidget::effectMosaic(bool aInit)
1332 {
1333     int dim    = 10;         // Size of a cell (dim x dim)
1334     int margin = dim + (int)(dim / 4);
1335 
1336     if (aInit)
1337     {
1338         d->i           = 30; // giri totaly
1339         d->pixelMatrix = new bool*[width()];
1340 
1341         for (int x = 0 ; x < width() ; ++x)
1342         {
1343             d->pixelMatrix[x] = new bool[height()];
1344 
1345             for (int y = 0 ; y < height() ; ++y)
1346             {
1347                 d->pixelMatrix[x][y] = false;
1348             }
1349         }
1350     }
1351 
1352     if (d->i <= 0)
1353     {
1354         showCurrentImage();
1355         return -1;
1356     }
1357 
1358     int w = width();
1359     int h = height();
1360 
1361     QPainter bufferPainter(&m_buffer);
1362 
1363     for (int x = 0 ; x < w ; x += (qrand() % margin) + dim)
1364     {
1365         for (int y = 0 ; y < h ; y += (qrand() % margin) + dim)
1366         {
1367             if (d->pixelMatrix[x][y] == true)
1368             {
1369                 if (y != 0)
1370                 {
1371                     y--;
1372                 }
1373 
1374                 continue;
1375             }
1376 
1377             bufferPainter.fillRect(x, y, dim, dim, QBrush(d->currImage));
1378 
1379             for (int i = 0 ; i < dim && (x + i) < w ; ++i)
1380             {
1381                 for (int j = 0 ; j < dim && (y + j) < h ; ++j)
1382                 {
1383                     d->pixelMatrix[x+i][y+j] = true;
1384                 }
1385             }
1386         }
1387     }
1388 
1389     bufferPainter.end();
1390     repaint();
1391     d->i--;
1392 
1393     return 20;
1394 }
1395 
effectCubism(bool aInit)1396 int PresentationWidget::effectCubism(bool aInit)
1397 {
1398     if (aInit)
1399     {
1400         d->alpha = M_PI * 2;
1401         d->w     = width();
1402         d->h     = height();
1403         d->i     = 150;
1404     }
1405 
1406     if (d->i <= 0)
1407     {
1408         showCurrentImage();
1409         return -1;
1410     }
1411 
1412     QPainterPath painterPath;
1413     QPainter bufferPainter(&m_buffer);
1414 
1415     d->x   = qrand() % d->w;
1416     d->y   = qrand() % d->h;
1417     int r  = (qrand() % 100) + 100;
1418     m_px   = d->x - r;
1419     m_py   = d->y - r;
1420     m_psx  = r;
1421     m_psy  = r;
1422 
1423     QTransform transform;
1424     transform.rotate((qrand() % 20) - 10);
1425     QRect rect(m_px, m_py, m_psx, m_psy);
1426     bufferPainter.setTransform(transform);
1427     bufferPainter.fillRect(rect, QBrush(d->currImage));
1428     bufferPainter.end();
1429     repaint();
1430 
1431     d->i--;
1432 
1433     return 10;
1434 }
1435 
effectRandom(bool)1436 int PresentationWidget::effectRandom(bool /*aInit*/)
1437 {
1438     d->fileIndex--;
1439 
1440     return -1;
1441 }
1442 
effectGrowing(bool aInit)1443 int PresentationWidget::effectGrowing(bool aInit)
1444 {
1445     if (aInit)
1446     {
1447         d->w  = width();
1448         d->h  = height();
1449         d->x  = d->w >> 1;
1450         d->y  = d->h >> 1;
1451         d->i  = 0;
1452         d->fx = d->x / 100.0;
1453         d->fy = d->y / 100.0;
1454     }
1455 
1456     d->x = (d->w >> 1) - (int)(d->i * d->fx);
1457     d->y = (d->h >> 1) - (int)(d->i * d->fy);
1458     d->i++;
1459 
1460     if ((d->x < 0) || (d->y < 0))
1461     {
1462         showCurrentImage();
1463 
1464         return -1;
1465     }
1466 
1467     m_px  = d->x;
1468     m_py  = d->y;
1469     m_psx = d->w - (d->x << 1);
1470     m_psy = d->h - (d->y << 1);
1471 
1472     QPainter bufferPainter(&m_buffer);
1473     bufferPainter.fillRect(m_px, m_py, m_psx, m_psy, QBrush(d->currImage));
1474     bufferPainter.end();
1475     repaint();
1476 
1477     return 20;
1478 }
1479 
effectHorizLines(bool aInit)1480 int PresentationWidget::effectHorizLines(bool aInit)
1481 {
1482     static int iyPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
1483 
1484     if (aInit)
1485     {
1486         d->w = width();
1487         d->h = height();
1488         d->i = 0;
1489     }
1490 
1491     if (iyPos[d->i] < 0)
1492     {
1493         return -1;
1494     }
1495 
1496     int iPos;
1497     int until = d->h;
1498 
1499     QPainter bufferPainter(&m_buffer);
1500     QBrush brush = QBrush(d->currImage);
1501 
1502     for (iPos = iyPos[d->i] ; iPos < until ; iPos += 8)
1503     {
1504         bufferPainter.fillRect(0, iPos, d->w, 1, brush);
1505     }
1506 
1507     bufferPainter.end();
1508     repaint();
1509 
1510     d->i++;
1511 
1512     if (iyPos[d->i] >= 0)
1513     {
1514         return 160;
1515     }
1516 
1517     showCurrentImage();
1518 
1519     return -1;
1520 }
1521 
effectVertLines(bool aInit)1522 int PresentationWidget::effectVertLines(bool aInit)
1523 {
1524     static int ixPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
1525 
1526     if (aInit)
1527     {
1528         d->w = width();
1529         d->h = height();
1530         d->i = 0;
1531     }
1532 
1533     if (ixPos[d->i] < 0)
1534     {
1535         return -1;
1536     }
1537 
1538     int iPos;
1539     int until = d->w;
1540 
1541     QPainter bufferPainter(&m_buffer);
1542     QBrush brush = QBrush(d->currImage);
1543 
1544     for (iPos = ixPos[d->i] ; iPos < until ; iPos += 8)
1545     {
1546         bufferPainter.fillRect(iPos, 0, 1, d->h, brush);
1547     }
1548 
1549     bufferPainter.end();
1550     repaint();
1551 
1552     d->i++;
1553 
1554     if (ixPos[d->i] >= 0)
1555     {
1556         return 160;
1557     }
1558 
1559     showCurrentImage();
1560 
1561     return -1;
1562 }
1563 
effectMultiCircleOut(bool aInit)1564 int PresentationWidget::effectMultiCircleOut(bool aInit)
1565 {
1566     int x, y, i;
1567     double alpha;
1568 
1569     if (aInit)
1570     {
1571         startPainter();
1572         d->w     = width();
1573         d->h     = height();
1574         d->x     = d->w;
1575         d->y     = d->h >> 1;
1576         d->pa.setPoint(0, d->w >> 1, d->h >> 1);
1577         d->pa.setPoint(3, d->w >> 1, d->h >> 1);
1578         d->fy    = sqrt((double)d->w * d->w + d->h * d->h) / 2;
1579         d->i     = qrand() % 15 + 2;
1580         d->fd    = M_PI * 2 / d->i;
1581         d->alpha = d->fd;
1582         d->wait  = 10 * d->i;
1583         d->fx    = M_PI / 32;  // divisor must be powers of 8
1584     }
1585 
1586     if (d->alpha < 0)
1587     {
1588         showCurrentImage();
1589 
1590         return -1;
1591     }
1592 
1593     for (alpha = d->alpha, i = d->i ; i >= 0 ; --i, alpha += d->fd)
1594     {
1595         x    = (d->w >> 1) + (int)(d->fy * cos(-alpha));
1596         y    = (d->h >> 1) + (int)(d->fy * sin(-alpha));
1597         d->x = (d->w >> 1) + (int)(d->fy * cos(-alpha + d->fx));
1598         d->y = (d->h >> 1) + (int)(d->fy * sin(-alpha + d->fx));
1599 
1600         d->pa.setPoint(1, x, y);
1601         d->pa.setPoint(2, d->x, d->y);
1602 
1603         QPainterPath painterPath;
1604         painterPath.addPolygon(QPolygon(d->pa));
1605 
1606         QPainter bufferPainter(&m_buffer);
1607         bufferPainter.fillPath(painterPath, QBrush(d->currImage));
1608         bufferPainter.end();
1609 
1610         repaint();
1611     }
1612 
1613     d->alpha -= d->fx;
1614 
1615     return d->wait;
1616 }
1617 
effectSpiralIn(bool aInit)1618 int PresentationWidget::effectSpiralIn(bool aInit)
1619 {
1620     if (aInit)
1621     {
1622         update();
1623         d->w  = width();
1624         d->h  = height();
1625         d->ix = d->w / 8;
1626         d->iy = d->h / 8;
1627         d->x0 = 0;
1628         d->x1 = d->w - d->ix;
1629         d->y0 = d->iy;
1630         d->y1 = d->h - d->iy;
1631         d->dx = d->ix;
1632         d->dy = 0;
1633         d->i  = 0;
1634         d->j  = 16 * 16;
1635         d->x  = 0;
1636         d->y  = 0;
1637     }
1638 
1639     if ((d->i == 0) && (d->x0 >= d->x1))
1640     {
1641         showCurrentImage();
1642 
1643         return -1;
1644     }
1645 
1646     if      ((d->i == 0) && (d->x >= d->x1))      // switch to: down on right side
1647     {
1648         d->i   = 1;
1649         d->dx  = 0;
1650         d->dy  = d->iy;
1651         d->x1 -= d->ix;
1652     }
1653     else if ((d->i == 1) && (d->y >= d->y1)) // switch to: right to left on bottom side
1654     {
1655         d->i   = 2;
1656         d->dx  = -d->ix;
1657         d->dy  = 0;
1658         d->y1 -= d->iy;
1659     }
1660     else if ((d->i == 2) && (d->x <= d->x0)) // switch to: up on left side
1661     {
1662         d->i   = 3;
1663         d->dx  = 0;
1664         d->dy  = -d->iy;
1665         d->x0 += d->ix;
1666     }
1667     else if ((d->i == 3) && (d->y <= d->y0)) // switch to: left to right on top side
1668     {
1669         d->i   = 0;
1670         d->dx  = d->ix;
1671         d->dy  = 0;
1672         d->y0 += d->iy;
1673     }
1674 
1675     m_px  = d->x;
1676     m_py  = d->y;
1677     m_psx = d->ix;
1678     m_psy = d->iy;
1679 
1680     QPainter bufferPainter(&m_buffer);
1681     bufferPainter.fillRect(m_px, m_py, m_psx, m_psy, QBrush(d->currImage));
1682     bufferPainter.end();
1683     repaint();
1684 
1685     d->x += d->dx;
1686     d->y += d->dy;
1687     d->j--;
1688 
1689     return 8;
1690 }
1691 
effectCircleOut(bool aInit)1692 int PresentationWidget::effectCircleOut(bool aInit)
1693 {
1694     int x, y;
1695 
1696     if (aInit)
1697     {
1698         startPainter();
1699         d->w     = width();
1700         d->h     = height();
1701         d->x     = d->w;
1702         d->y     = d->h >> 1;
1703         d->alpha = 2 * M_PI;
1704         d->pa.setPoint(0, d->w >> 1, d->h >> 1);
1705         d->pa.setPoint(3, d->w >> 1, d->h >> 1);
1706         d->fx    = M_PI / 16;                       // divisor must be powers of 8
1707         d->fy    = sqrt((double)d->w * d->w + d->h * d->h) / 2;
1708     }
1709 
1710     if (d->alpha < 0)
1711     {
1712         showCurrentImage();
1713 
1714         return -1;
1715     }
1716 
1717     x         = d->x;
1718     y         = d->y;
1719     d->x      = (d->w >> 1) + (int)(d->fy * cos(d->alpha));
1720     d->y      = (d->h >> 1) + (int)(d->fy * sin(d->alpha));
1721     d->alpha -= d->fx;
1722 
1723     d->pa.setPoint(1, x, y);
1724     d->pa.setPoint(2, d->x, d->y);
1725 
1726     QPainterPath painterPath;
1727     painterPath.addPolygon(QPolygon(d->pa));
1728     QPainter bufferPainter(&m_buffer);
1729     bufferPainter.fillPath(painterPath, QBrush(d->currImage));
1730     bufferPainter.end();
1731     repaint();
1732 
1733     return 20;
1734 }
1735 
effectBlobs(bool aInit)1736 int PresentationWidget::effectBlobs(bool aInit)
1737 {
1738     int r;
1739 
1740     if (aInit)
1741     {
1742         d->alpha = M_PI * 2;
1743         d->w     = width();
1744         d->h     = height();
1745         d->i     = 150;
1746     }
1747 
1748     if (d->i <= 0)
1749     {
1750         showCurrentImage();
1751 
1752         return -1;
1753     }
1754 
1755     d->x   = qrand() % d->w;
1756     d->y   = qrand() % d->h;
1757     r      = (qrand() % 200) + 50;
1758     m_px   = d->x - r;
1759     m_py   = d->y - r;
1760     m_psx  = r;
1761     m_psy  = r;
1762 
1763     QPainterPath painterPath;
1764     painterPath.addEllipse(m_px, m_py, m_psx, m_psy);
1765     QPainter bufferPainter(&m_buffer);
1766     bufferPainter.fillPath(painterPath, QBrush(d->currImage));
1767     bufferPainter.end();
1768     repaint();
1769 
1770     d->i--;
1771 
1772     return 10;
1773 }
1774 
1775 } // namespace DigikamGenericPresentationPlugin
1776