File indexing completed on 2025-03-09 03:52:10

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2014-09-18
0007  * Description : slideshow OSD widget
0008  *
0009  * SPDX-FileCopyrightText: 2014-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2019-2020 by Minh Nghia Duong <minhnghiaduong997 at gmail dot com>
0011  * SPDX-FileCopyrightText:      2021 by Phuoc Khanh Le <phuockhanhnk94 at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "slideosd.h"
0018 
0019 // Qt includes
0020 
0021 #include <QApplication>
0022 #include <QProgressBar>
0023 #include <QLayout>
0024 #include <QTimer>
0025 #include <QEvent>
0026 #include <QStyle>
0027 
0028 // Local includes
0029 
0030 #include "digikam_debug.h"
0031 #include "slideshowloader.h"
0032 #include "slidetoolbar.h"
0033 #include "slideproperties.h"
0034 #include "ratingwidget.h"
0035 #include "colorlabelwidget.h"
0036 #include "picklabelwidget.h"
0037 #include "dinfointerface.h"
0038 
0039 using namespace Digikam;
0040 
0041 namespace DigikamGenericSlideShowPlugin
0042 {
0043 
0044 class Q_DECL_HIDDEN SlideOSD::Private
0045 {
0046 public:
0047 
0048     explicit Private()
0049       : paused          (false),
0050         video           (false),
0051         blink           (false),
0052         ready           (false),
0053         refresh         (1000),       ///< Progress bar refresh in ms
0054         progressBar     (nullptr),
0055         progressTimer   (nullptr),
0056         labelsBox       (nullptr),
0057         progressBox     (nullptr),
0058         parent          (nullptr),
0059         slideProps      (nullptr),
0060         toolBar         (nullptr),
0061         ratingWidget    (nullptr),
0062         clWidget        (nullptr),
0063         plWidget        (nullptr),
0064         settings        (nullptr)
0065     {
0066     }
0067 
0068     bool                paused;
0069     bool                video;
0070     bool                blink;
0071     bool                ready;
0072 
0073     int const           refresh;
0074 
0075     QProgressBar*       progressBar;
0076     QTimer*             progressTimer;
0077 
0078     DHBox*              labelsBox;
0079     DHBox*              progressBox;
0080 
0081     SlideShowLoader*    parent;
0082     SlideProperties*    slideProps;
0083     SlideToolBar*       toolBar;
0084     RatingWidget*       ratingWidget;
0085     ColorLabelSelector* clWidget;
0086     PickLabelSelector*  plWidget;
0087     SlideShowSettings*  settings;
0088 };
0089 
0090 SlideOSD::SlideOSD(SlideShowSettings* const settings, SlideShowLoader* const parent)
0091     : QWidget(parent),
0092       d      (new Private())
0093 {
0094     Qt::WindowFlags flags = Qt::FramelessWindowHint  |
0095                             Qt::WindowStaysOnTopHint |
0096                             Qt::X11BypassWindowManagerHint;
0097 
0098     setWindowFlags(flags);
0099     setAttribute(Qt::WA_TranslucentBackground, true);
0100     setAttribute(Qt::WA_ShowWithoutActivating, true);
0101     setMouseTracking(true);
0102 
0103     d->parent       = parent;
0104     d->settings     = settings;
0105 
0106     d->slideProps   = new SlideProperties(d->settings, this);
0107 
0108     // ---------------------------------------------------------------
0109 
0110     d->labelsBox    = new DHBox(this);
0111 
0112     d->clWidget     = new ColorLabelSelector(d->labelsBox);
0113     d->clWidget->setFocusPolicy(Qt::NoFocus);
0114     d->clWidget->setMouseTracking(true);
0115 
0116     d->plWidget     = new PickLabelSelector(d->labelsBox);
0117     d->plWidget->setFocusPolicy(Qt::NoFocus);
0118     d->plWidget->setMouseTracking(true);
0119 
0120     d->ratingWidget = new RatingWidget(d->labelsBox);
0121     d->ratingWidget->setTracking(false);
0122     d->ratingWidget->setFading(false);
0123     d->ratingWidget->setFocusPolicy(Qt::NoFocus);
0124     d->ratingWidget->setMouseTracking(true);
0125 
0126     d->labelsBox->layout()->setAlignment(d->ratingWidget, Qt::AlignVCenter | Qt::AlignLeft);
0127     d->labelsBox->setMouseTracking(true);
0128 
0129     d->labelsBox->setVisible(d->settings->printLabels || d->settings->printRating);
0130     d->ratingWidget->setVisible(d->settings->printRating);
0131     d->clWidget->setVisible(d->settings->printLabels);
0132     d->plWidget->setVisible(d->settings->printLabels);
0133 
0134     connect(d->ratingWidget, SIGNAL(signalRatingChanged(int)),
0135             parent, SLOT(slotAssignRating(int)));
0136 
0137     connect(d->clWidget, SIGNAL(signalColorLabelChanged(int)),
0138             parent, SLOT(slotAssignColorLabel(int)));
0139 
0140     connect(d->plWidget, SIGNAL(signalPickLabelChanged(int)),
0141             parent, SLOT(slotAssignPickLabel(int)));
0142 
0143     // ---------------------------------------------------------------
0144 
0145     d->progressBox   = new DHBox(this);
0146     d->progressBox->setVisible(d->settings->showProgressIndicator);
0147     d->progressBox->setMouseTracking(true);
0148 
0149     d->progressBar   = new QProgressBar(d->progressBox);
0150     d->progressBar->setMinimum(0);
0151     d->progressBar->setMaximum(d->settings->delay);
0152     d->progressBar->setFocusPolicy(Qt::NoFocus);
0153     d->progressBar->setMouseTracking(true);
0154 
0155     d->toolBar       = new SlideToolBar(d->settings, d->progressBox);
0156 
0157     // ---------------------------------------------------------------
0158 
0159     d->slideProps->installEventFilter(d->parent);
0160     d->clWidget->installEventFilter(this);
0161     d->clWidget->installEventFilter(d->parent);
0162     d->clWidget->colorLabelWidget()->installEventFilter(this);
0163     d->plWidget->installEventFilter(this);
0164     d->plWidget->installEventFilter(d->parent);
0165     d->plWidget->pickLabelWidget()->installEventFilter(this);
0166     d->ratingWidget->installEventFilter(this);
0167     d->ratingWidget->installEventFilter(d->parent);
0168     d->labelsBox->installEventFilter(d->parent);
0169     d->progressBox->installEventFilter(d->parent);
0170     d->progressBar->installEventFilter(d->parent);
0171     d->toolBar->installEventFilter(this);
0172     d->toolBar->installEventFilter(d->parent);
0173 
0174     // ---------------------------------------------------------------
0175 
0176     connect(d->toolBar, SIGNAL(signalPause()),
0177             d->parent, SLOT(slotPause()));
0178 
0179     connect(d->toolBar, SIGNAL(signalPlay()),
0180             d->parent, SLOT(slotPlay()));
0181 
0182     connect(d->toolBar, SIGNAL(signalNext()),
0183             d->parent, SLOT(slotLoadNextItem()));
0184 
0185     connect(d->toolBar, SIGNAL(signalPrev()),
0186             d->parent, SLOT(slotLoadPrevItem()));
0187 
0188     connect(d->toolBar, SIGNAL(signalClose()),
0189             d->parent, SLOT(close()));
0190 
0191     connect(d->toolBar, SIGNAL(signalRemoveImageFromList()),
0192             d->parent, SLOT(slotRemoveImageFromList()));
0193 
0194     connect(d->toolBar, SIGNAL(signalUpdateSettings()),
0195             this, SLOT(slotUpdateSettings()));
0196 
0197     connect(d->toolBar, SIGNAL(signalScreenSelected(int)),
0198             d->parent, SLOT(slotScreenSelected(int)));
0199 
0200     // ---------------------------------------------------------------
0201 
0202     QGridLayout* const grid = new QGridLayout(this);
0203     grid->addWidget(d->slideProps,  0, 0, 1, 2);
0204     grid->addWidget(d->labelsBox,   1, 0, 1, 1);
0205     grid->addWidget(d->progressBox, 2, 0, 1, 1);
0206     grid->setRowStretch(0, 10);
0207     grid->setColumnStretch(1, 10);
0208     grid->setContentsMargins(QMargins());
0209     grid->setSpacing(qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0210                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)));
0211 
0212     // ---------------------------------------------------------------
0213 
0214     d->progressTimer = new QTimer(this);
0215     d->progressTimer->setSingleShot(false);
0216 
0217     connect(d->progressTimer, SIGNAL(timeout()),
0218             this, SLOT(slotProgressTimer()));
0219 
0220     QTimer::singleShot(500, this, SLOT(slotStart()));
0221 }
0222 
0223 SlideOSD::~SlideOSD()
0224 {
0225     d->progressTimer->stop();
0226 
0227     delete d;
0228 }
0229 
0230 void SlideOSD::slotStart()
0231 {
0232     d->settings->suffleImages();
0233     d->parent->slotLoadNextItem();
0234     d->progressTimer->start(d->refresh);
0235     pause(!d->settings->autoPlayEnabled);
0236 }
0237 
0238 void SlideOSD::slotUpdateSettings()
0239 {
0240     d->labelsBox->setVisible(d->settings->printLabels || d->settings->printRating);
0241     d->progressBox->setVisible(d->settings->showProgressIndicator);
0242     d->ratingWidget->setVisible(d->settings->printRating);
0243     d->clWidget->setVisible(d->settings->printLabels);
0244     d->plWidget->setVisible(d->settings->printLabels);
0245     d->progressBar->setMaximum(d->settings->delay);
0246     d->settings->suffleImages();
0247 }
0248 
0249 SlideToolBar* SlideOSD::toolBar() const
0250 {
0251     return d->toolBar;
0252 }
0253 
0254 void SlideOSD::setCurrentUrl(const QUrl& url)
0255 {
0256     DItemInfo item(d->settings->iface->itemInfo(url));
0257 
0258     // Update info text.
0259 
0260     d->slideProps->setCurrentUrl(url);
0261 
0262     // Display Labels.
0263 
0264     if (d->settings->printLabels)
0265     {
0266         d->clWidget->blockSignals(true);
0267         d->plWidget->blockSignals(true);
0268         d->clWidget->setColorLabel((ColorLabel)item.colorLabel());
0269         d->plWidget->setPickLabel((PickLabel)item.pickLabel());
0270         d->clWidget->blockSignals(false);
0271         d->plWidget->blockSignals(false);
0272     }
0273 
0274     if (d->settings->printRating)
0275     {
0276         d->ratingWidget->blockSignals(true);
0277         d->ratingWidget->setRating(item.rating());
0278         d->ratingWidget->blockSignals(false);
0279     }
0280 
0281     // Make the OSD the proper size
0282 
0283     resize(d->parent->width() - 10, d->parent->height());
0284     move(10, 0);
0285     raise();
0286 }
0287 
0288 QSize SlideOSD::slideShowSize() const
0289 {
0290     return d->parent->size();
0291 }
0292 
0293 bool SlideOSD::eventFilter(QObject* obj, QEvent* ev)
0294 {
0295     if (
0296         (obj == d->labelsBox)                    ||
0297         (obj == d->ratingWidget)                 ||
0298         (obj == d->clWidget)                     ||
0299         (obj == d->plWidget)                     ||
0300         (obj == d->clWidget->colorLabelWidget()) ||
0301         (obj == d->plWidget->pickLabelWidget())
0302        )
0303     {
0304         if (ev->type() == QEvent::Enter)
0305         {
0306             d->paused = isPaused();
0307             d->parent->slotPause();
0308 
0309             return false;
0310         }
0311 
0312         if (ev->type() == QEvent::Leave)
0313         {
0314             if (!d->paused)
0315             {
0316                 d->parent->slotPlay();
0317             }
0318 
0319             return false;
0320         }
0321     }
0322 
0323     // pass the event on to the parent class
0324 
0325     return QWidget::eventFilter(obj, ev);
0326 }
0327 
0328 void SlideOSD::slotProgressTimer()
0329 {
0330     QString str = QString::fromUtf8("(%1/%2)")
0331                     .arg(d->settings->fileList.indexOf(d->parent->currentItem()) + 1)
0332                     .arg(d->settings->fileList.count());
0333 
0334     if      (isPaused())
0335     {
0336         d->blink = !d->blink;
0337 
0338         if (d->blink)
0339         {
0340             str = QString();
0341         }
0342 
0343         d->progressBar->setFormat(str);
0344     }
0345     else if (d->video)
0346     {
0347         d->progressBar->setFormat(str);
0348         return;
0349     }
0350     else
0351     {
0352         d->progressBar->setFormat(str);
0353         d->progressBar->setMaximum(d->settings->delay);
0354 
0355         if (d->progressBar->value() == d->settings->delay)
0356         {
0357             if (!d->ready)
0358             {
0359                 return;
0360             }
0361 
0362             d->ready = false;
0363             d->parent->slotLoadNextItem();
0364         }
0365 
0366         d->progressBar->setValue(d->progressBar->value()+1);
0367     }
0368 }
0369 
0370 void SlideOSD::pause(bool b)
0371 {
0372     d->toolBar->pause(b);
0373 
0374     if (!b)
0375     {
0376         d->progressBar->setValue(0);
0377     }
0378 }
0379 
0380 void SlideOSD::video(bool b)
0381 {
0382     d->video = b;
0383 }
0384 
0385 bool SlideOSD::isPaused() const
0386 {
0387     return d->toolBar->isPaused();
0388 }
0389 
0390 bool SlideOSD::isUnderMouse() const
0391 {
0392     return (
0393             d->ratingWidget->underMouse() ||
0394             d->progressBar->underMouse()  ||
0395             d->clWidget->underMouse()     ||
0396             d->plWidget->underMouse()     ||
0397             d->toolBar->underMouse()
0398            );
0399 }
0400 
0401 void SlideOSD::setLoadingReady(bool b)
0402 {
0403     d->ready = b;
0404 }
0405 
0406 } // namespace DigikamGenericSlideShowPlugin
0407 
0408 #include "moc_slideosd.cpp"