1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2014-09-18
7 * Description : slideshow OSD widget
8 *
9 * Copyright (C) 2014-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2019-2020 by Minh Nghia Duong <minhnghiaduong997 at gmail dot com>
11 * Copyright (C) 2021 by Phuoc Khanh Le <phuockhanhnk94 at gmail dot com>
12 *
13 * This program is free software; you can redistribute it
14 * and/or modify it under the terms of the GNU General
15 * Public License as published by the Free Software Foundation;
16 * either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * ============================================================ */
25
26 #include "slideosd.h"
27
28 // Qt includes
29
30 #include <QApplication>
31 #include <QProgressBar>
32 #include <QLayout>
33 #include <QTimer>
34 #include <QEvent>
35 #include <QStyle>
36
37 // Local includes
38
39 #include "digikam_debug.h"
40 #include "slideshowloader.h"
41 #include "slidetoolbar.h"
42 #include "slideproperties.h"
43 #include "ratingwidget.h"
44 #include "colorlabelwidget.h"
45 #include "picklabelwidget.h"
46 #include "dinfointerface.h"
47
48 using namespace Digikam;
49
50 namespace DigikamGenericSlideShowPlugin
51 {
52
53 class Q_DECL_HIDDEN SlideOSD::Private
54 {
55 public:
56
Private()57 explicit Private()
58 : paused (false),
59 video (false),
60 blink (false),
61 ready (false),
62 refresh (1000), ///< Progress bar refresh in ms
63 progressBar (nullptr),
64 progressTimer (nullptr),
65 labelsBox (nullptr),
66 progressBox (nullptr),
67 parent (nullptr),
68 slideProps (nullptr),
69 toolBar (nullptr),
70 ratingWidget (nullptr),
71 clWidget (nullptr),
72 plWidget (nullptr),
73 settings (nullptr)
74 {
75 }
76
77 bool paused;
78 bool video;
79 bool blink;
80 bool ready;
81
82 int const refresh;
83
84 QProgressBar* progressBar;
85 QTimer* progressTimer;
86
87 DHBox* labelsBox;
88 DHBox* progressBox;
89
90 SlideShowLoader* parent;
91 SlideProperties* slideProps;
92 SlideToolBar* toolBar;
93 RatingWidget* ratingWidget;
94 ColorLabelSelector* clWidget;
95 PickLabelSelector* plWidget;
96 SlideShowSettings* settings;
97 };
98
SlideOSD(SlideShowSettings * const settings,SlideShowLoader * const parent)99 SlideOSD::SlideOSD(SlideShowSettings* const settings, SlideShowLoader* const parent)
100 : QWidget(parent),
101 d (new Private())
102 {
103 Qt::WindowFlags flags = Qt::FramelessWindowHint |
104 Qt::WindowStaysOnTopHint |
105 Qt::X11BypassWindowManagerHint;
106
107 setWindowFlags(flags);
108 setAttribute(Qt::WA_TranslucentBackground, true);
109 setAttribute(Qt::WA_ShowWithoutActivating, true);
110 setMouseTracking(true);
111
112 d->parent = parent;
113 d->settings = settings;
114
115 d->slideProps = new SlideProperties(d->settings, this);
116 d->slideProps->installEventFilter(d->parent);
117
118 // ---------------------------------------------------------------
119
120 d->labelsBox = new DHBox(this);
121
122 d->clWidget = new ColorLabelSelector(d->labelsBox);
123 d->clWidget->installEventFilter(this);
124 d->clWidget->installEventFilter(d->parent);
125 d->clWidget->colorLabelWidget()->installEventFilter(this);
126 d->clWidget->setFocusPolicy(Qt::NoFocus);
127 d->clWidget->setMouseTracking(true);
128
129 d->plWidget = new PickLabelSelector(d->labelsBox);
130 d->plWidget->installEventFilter(this);
131 d->plWidget->installEventFilter(d->parent);
132 d->plWidget->setFocusPolicy(Qt::NoFocus);
133 d->plWidget->pickLabelWidget()->installEventFilter(this);
134 d->plWidget->setMouseTracking(true);
135
136 d->ratingWidget = new RatingWidget(d->labelsBox);
137 d->ratingWidget->setTracking(false);
138 d->ratingWidget->setFading(false);
139 d->ratingWidget->installEventFilter(this);
140 d->ratingWidget->installEventFilter(d->parent);
141 d->ratingWidget->setFocusPolicy(Qt::NoFocus);
142 d->ratingWidget->setMouseTracking(true);
143
144 d->labelsBox->layout()->setAlignment(d->ratingWidget, Qt::AlignVCenter | Qt::AlignLeft);
145 d->labelsBox->installEventFilter(d->parent);
146 d->labelsBox->setMouseTracking(true);
147
148 d->labelsBox->setVisible(d->settings->printLabels || d->settings->printRating);
149 d->ratingWidget->setVisible(d->settings->printRating);
150 d->clWidget->setVisible(d->settings->printLabels);
151 d->plWidget->setVisible(d->settings->printLabels);
152
153 connect(d->ratingWidget, SIGNAL(signalRatingChanged(int)),
154 parent, SLOT(slotAssignRating(int)));
155
156 connect(d->clWidget, SIGNAL(signalColorLabelChanged(int)),
157 parent, SLOT(slotAssignColorLabel(int)));
158
159 connect(d->plWidget, SIGNAL(signalPickLabelChanged(int)),
160 parent, SLOT(slotAssignPickLabel(int)));
161
162 // ---------------------------------------------------------------
163
164 d->progressBox = new DHBox(this);
165 d->progressBox->setVisible(d->settings->showProgressIndicator);
166 d->progressBox->installEventFilter(d->parent);
167 d->progressBox->setMouseTracking(true);
168
169 d->progressBar = new QProgressBar(d->progressBox);
170 d->progressBar->setMinimum(0);
171 d->progressBar->setMaximum(d->settings->delay);
172 d->progressBar->setFocusPolicy(Qt::NoFocus);
173 d->progressBar->installEventFilter(d->parent);
174 d->progressBar->setMouseTracking(true);
175
176 d->toolBar = new SlideToolBar(d->settings, d->progressBox);
177 d->toolBar->installEventFilter(this);
178 d->toolBar->installEventFilter(d->parent);
179
180 connect(d->toolBar, SIGNAL(signalPause()),
181 d->parent, SLOT(slotPause()));
182
183 connect(d->toolBar, SIGNAL(signalPlay()),
184 d->parent, SLOT(slotPlay()));
185
186 connect(d->toolBar, SIGNAL(signalNext()),
187 d->parent, SLOT(slotLoadNextItem()));
188
189 connect(d->toolBar, SIGNAL(signalPrev()),
190 d->parent, SLOT(slotLoadPrevItem()));
191
192 connect(d->toolBar, SIGNAL(signalClose()),
193 d->parent, SLOT(close()));
194
195 connect(d->toolBar, SIGNAL(signalRemoveImageFromList()),
196 d->parent, SLOT(slotRemoveImageFromList()));
197
198 connect(d->toolBar, SIGNAL(signalUpdateSettings()),
199 this, SLOT(slotUpdateSettings()));
200
201 connect(d->toolBar, SIGNAL(signalScreenSelected(int)),
202 d->parent, SLOT(slotScreenSelected(int)));
203
204 // ---------------------------------------------------------------
205
206 QGridLayout* const grid = new QGridLayout(this);
207 grid->addWidget(d->slideProps, 0, 0, 1, 2);
208 grid->addWidget(d->labelsBox, 1, 0, 1, 1);
209 grid->addWidget(d->progressBox, 2, 0, 1, 1);
210 grid->setRowStretch(0, 10);
211 grid->setColumnStretch(1, 10);
212 grid->setContentsMargins(QMargins());
213 grid->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
214
215 // ---------------------------------------------------------------
216
217 d->progressTimer = new QTimer(this);
218 d->progressTimer->setSingleShot(false);
219
220 connect(d->progressTimer, SIGNAL(timeout()),
221 this, SLOT(slotProgressTimer()));
222
223 QTimer::singleShot(500, this, SLOT(slotStart()));
224 }
225
~SlideOSD()226 SlideOSD::~SlideOSD()
227 {
228 d->progressTimer->stop();
229
230 delete d;
231 }
232
slotStart()233 void SlideOSD::slotStart()
234 {
235 d->settings->suffleImages();
236 d->parent->slotLoadNextItem();
237 d->progressTimer->start(d->refresh);
238 pause(!d->settings->autoPlayEnabled);
239 }
240
slotUpdateSettings()241 void SlideOSD::slotUpdateSettings()
242 {
243 d->labelsBox->setVisible(d->settings->printLabels || d->settings->printRating);
244 d->progressBox->setVisible(d->settings->showProgressIndicator);
245 d->ratingWidget->setVisible(d->settings->printRating);
246 d->clWidget->setVisible(d->settings->printLabels);
247 d->plWidget->setVisible(d->settings->printLabels);
248 d->progressBar->setMaximum(d->settings->delay);
249 d->settings->suffleImages();
250 }
251
toolBar() const252 SlideToolBar* SlideOSD::toolBar() const
253 {
254 return d->toolBar;
255 }
256
setCurrentUrl(const QUrl & url)257 void SlideOSD::setCurrentUrl(const QUrl& url)
258 {
259 DInfoInterface::DInfoMap info = d->settings->iface->itemInfo(url);
260 DItemInfo item(info);
261
262 // Update info text.
263
264 d->slideProps->setCurrentUrl(url);
265
266 // Display Labels.
267
268 if (d->settings->printLabels)
269 {
270 d->clWidget->blockSignals(true);
271 d->plWidget->blockSignals(true);
272 d->clWidget->setColorLabel((ColorLabel)item.colorLabel());
273 d->plWidget->setPickLabel((PickLabel)item.pickLabel());
274 d->clWidget->blockSignals(false);
275 d->plWidget->blockSignals(false);
276 }
277
278 if (d->settings->printRating)
279 {
280 d->ratingWidget->blockSignals(true);
281 d->ratingWidget->setRating(item.rating());
282 d->ratingWidget->blockSignals(false);
283 }
284
285 // Make the OSD the proper size
286
287 resize(d->parent->width() - 10, d->parent->height());
288 move(10, 0);
289 raise();
290 }
291
slideShowSize() const292 QSize SlideOSD::slideShowSize() const
293 {
294 return d->parent->size();
295 }
296
eventFilter(QObject * obj,QEvent * ev)297 bool SlideOSD::eventFilter(QObject* obj, QEvent* ev)
298 {
299 if (
300 (obj == d->labelsBox) ||
301 (obj == d->ratingWidget) ||
302 (obj == d->clWidget) ||
303 (obj == d->plWidget) ||
304 (obj == d->clWidget->colorLabelWidget()) ||
305 (obj == d->plWidget->pickLabelWidget())
306 )
307 {
308 if (ev->type() == QEvent::Enter)
309 {
310 d->paused = isPaused();
311 d->parent->slotPause();
312
313 return false;
314 }
315
316 if (ev->type() == QEvent::Leave)
317 {
318 if (!d->paused)
319 {
320 d->parent->slotPlay();
321 }
322
323 return false;
324 }
325 }
326
327 // pass the event on to the parent class
328
329 return QWidget::eventFilter(obj, ev);
330 }
331
slotProgressTimer()332 void SlideOSD::slotProgressTimer()
333 {
334 QString str = QString::fromUtf8("(%1/%2)")
335 .arg(QString::number(d->settings->fileList.indexOf(d->parent->currentItem()) + 1))
336 .arg(QString::number(d->settings->fileList.count()));
337
338 if (isPaused())
339 {
340 d->blink = !d->blink;
341
342 if (d->blink)
343 {
344 str = QString();
345 }
346
347 d->progressBar->setFormat(str);
348 }
349 else if (d->video)
350 {
351 d->progressBar->setFormat(str);
352 return;
353 }
354 else
355 {
356 d->progressBar->setFormat(str);
357 d->progressBar->setMaximum(d->settings->delay);
358
359 if (d->progressBar->value() == d->settings->delay)
360 {
361 if (!d->ready)
362 {
363 return;
364 }
365
366 d->ready = false;
367 d->parent->slotLoadNextItem();
368 }
369
370 d->progressBar->setValue(d->progressBar->value()+1);
371 }
372 }
373
pause(bool b)374 void SlideOSD::pause(bool b)
375 {
376 d->toolBar->pause(b);
377
378 if (!b)
379 {
380 d->progressBar->setValue(0);
381 }
382 }
383
video(bool b)384 void SlideOSD::video(bool b)
385 {
386 d->video = b;
387 }
388
isPaused() const389 bool SlideOSD::isPaused() const
390 {
391 return d->toolBar->isPaused();
392 }
393
isUnderMouse() const394 bool SlideOSD::isUnderMouse() const
395 {
396 return (
397 d->ratingWidget->underMouse() ||
398 d->progressBar->underMouse() ||
399 d->clWidget->underMouse() ||
400 d->plWidget->underMouse() ||
401 d->toolBar->underMouse()
402 );
403 }
404
toggleProperties()405 void SlideOSD::toggleProperties()
406 {
407 d->slideProps->togglePaintEnabled();
408 }
409
setLoadingReady(bool b)410 void SlideOSD::setLoadingReady(bool b)
411 {
412 d->ready = b;
413 }
414
415 } // namespace DigikamGenericSlideShowPlugin
416