1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2014-09-19
7 * Description : slide properties 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 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "slideproperties.h"
26
27 // Qt includes
28
29 #include <QTextDocument>
30 #include <QApplication>
31 #include <QDateTime>
32 #include <QPainter>
33 #include <QPixmap>
34 #include <QLocale>
35
36 // KDE includes
37
38 #include <klocalizedstring.h>
39
40 // Local includes
41
42 #include "digikam_debug.h"
43 #include "dinfointerface.h"
44 #include "itempropertiestab.h"
45
46 using namespace Digikam;
47
48 namespace DigikamGenericSlideShowPlugin
49 {
50
51 class Q_DECL_HIDDEN SlideProperties::Private
52 {
53 public:
54
Private()55 explicit Private()
56 : maxStringLen(80),
57 paintEnabled(true),
58 settings (nullptr)
59 {
60 }
61
62 const int maxStringLen;
63 bool paintEnabled;
64
65 QUrl url;
66
67 SlideShowSettings* settings;
68
69 DInfoInterface::DInfoMap infoMap;
70 };
71
SlideProperties(SlideShowSettings * const settings,QWidget * const parent)72 SlideProperties::SlideProperties(SlideShowSettings* const settings, QWidget* const parent)
73 : QWidget(parent),
74 d (new Private)
75 {
76 setMouseTracking(true);
77 d->settings = settings;
78 }
79
~SlideProperties()80 SlideProperties::~SlideProperties()
81 {
82 delete d;
83 }
84
setCurrentUrl(const QUrl & url)85 void SlideProperties::setCurrentUrl(const QUrl& url)
86 {
87 d->infoMap = d->settings->iface->itemInfo(url);
88 d->url = url;
89
90 update();
91 }
92
paintEvent(QPaintEvent *)93 void SlideProperties::paintEvent(QPaintEvent*)
94 {
95 if (!d->paintEnabled)
96 {
97 return;
98 }
99
100 QPainter p(this);
101 p.setFont(d->settings->captionFont);
102
103 DItemInfo item(d->infoMap);
104
105 QString str;
106 /*
107 PhotoInfoContainer photoInfo = d->info.photoInfo;
108 */
109 QString comment = item.comment();
110 QString title = item.title();
111 QStringList tags = item.keywords();
112 int offset = 0;
113
114 // Display tag names.
115
116 if (d->settings->printTags)
117 {
118 printTags(p, offset, tags);
119 }
120
121 // Display Titles.
122
123 if (d->settings->printTitle)
124 {
125 str.clear();
126
127 if (!title.isEmpty())
128 {
129 str += title;
130 printInfoText(p, offset, str);
131 }
132 }
133
134 // Display Captions if no Titles.
135
136 if (d->settings->printCapIfNoTitle)
137 {
138 str.clear();
139
140 if (title.isEmpty())
141 {
142 str += comment;
143 printComments(p, offset, str);
144 }
145 }
146
147 // Display Comments.
148
149 if (d->settings->printComment)
150 {
151 str = comment;
152 printComments(p, offset, str);
153 }
154
155 // Display Make and Model.
156
157 if (d->settings->printMakeModel)
158 {
159 str.clear();
160
161 QString make = item.make();
162 QString model = item.model();
163
164 if (!make.isEmpty())
165 {
166 ItemPropertiesTab::shortenedMakeInfo(make);
167 str = make;
168 }
169
170 if (!model.isEmpty())
171 {
172 if (!make.isEmpty())
173 {
174 str += QLatin1String(" / ");
175 }
176
177 ItemPropertiesTab::shortenedModelInfo(model);
178 str += model;
179 }
180
181 printInfoText(p, offset, str);
182 }
183
184 // Display Lens model.
185
186 if (d->settings->printLensModel)
187 {
188 str.clear();
189
190 QString lens = item.lens();
191
192 if (!lens.isEmpty())
193 {
194 str = lens;
195 printInfoText(p, offset, str);
196 }
197 }
198
199 // Display Exposure and Sensitivity.
200
201 if (d->settings->printExpoSensitivity)
202 {
203 str.clear();
204
205 QString exposureTime = item.exposureTime();
206 QString sensitivity = item.sensitivity();
207
208 if (!exposureTime.isEmpty())
209 {
210 str = exposureTime;
211 }
212
213 if (!sensitivity.isEmpty())
214 {
215 if (!exposureTime.isEmpty())
216 {
217 str += QLatin1String(" / ");
218 }
219
220 str += i18n("%1 ISO", sensitivity);
221 }
222
223 printInfoText(p, offset, str);
224 }
225
226 // Display Aperture and Focal.
227
228 if (d->settings->printApertureFocal)
229 {
230 str.clear();
231
232 QString aperture = item.aperture();
233 QString focalLength = item.focalLength();
234 QString focalLength35mm = item.focalLength35mm();
235
236 if (!aperture.isEmpty())
237 {
238 str = aperture;
239 }
240
241 if (focalLength35mm.isEmpty())
242 {
243 if (!focalLength.isEmpty())
244 {
245 if (!aperture.isEmpty())
246 {
247 str += QLatin1String(" / ");
248 }
249
250 str += focalLength;
251 }
252 }
253 else
254 {
255 if (!aperture.isEmpty())
256 {
257 str += QLatin1String(" / ");
258 }
259
260 if (!focalLength.isEmpty())
261 {
262 str += QString::fromUtf8("%1 (%2)").arg(focalLength).arg(focalLength35mm);
263 }
264 else
265 {
266 str += QString::fromUtf8("%1").arg(focalLength35mm);
267 }
268 }
269
270 printInfoText(p, offset, str);
271 }
272
273 // Display Creation Date.
274
275 if (d->settings->printDate)
276 {
277 QDateTime dateTime = item.dateTime();
278
279 if (dateTime.isValid())
280 {
281 str = QLocale().toString(dateTime, QLocale::ShortFormat);
282 printInfoText(p, offset, str);
283 }
284 }
285
286 // Display image File Name.
287
288 if (d->settings->printName)
289 {
290 printInfoText(p, offset, d->url.fileName());
291 }
292 }
293
printInfoText(QPainter & p,int & offset,const QString & str,const QColor & pcol)294 void SlideProperties::printInfoText(QPainter& p, int& offset, const QString& str, const QColor& pcol)
295 {
296 if (!str.isEmpty())
297 {
298 offset += QFontMetrics(p.font()).lineSpacing();
299 p.setPen(Qt::black);
300
301 for (int x = -1 ; x <= 1 ; ++x)
302 {
303 for (int y = offset + 1 ; y >= offset - 1 ; --y)
304 {
305 p.drawText(x, p.window().height() - y, str);
306 }
307 }
308
309 p.setPen(pcol);
310 p.drawText(0, p.window().height() - offset, str);
311 }
312 }
313
printComments(QPainter & p,int & offset,const QString & comments)314 void SlideProperties::printComments(QPainter& p, int& offset, const QString& comments)
315 {
316 QStringList commentsByLines;
317
318 uint commentsIndex = 0; // Comments QString index
319
320 while (commentsIndex < (uint)comments.length())
321 {
322 QString newLine;
323 bool breakLine = false; // End Of Line found
324 uint currIndex; // Comments QString current index
325
326 // Check minimal lines dimension
327
328 uint commentsLinesLengthLocal = d->maxStringLen;
329
330 for (currIndex = commentsIndex ;
331 (currIndex < (uint)comments.length()) && !breakLine ; ++currIndex)
332 {
333 if ((comments.at(currIndex) == QLatin1Char('\n')) || comments.at(currIndex).isSpace())
334 {
335 breakLine = true;
336 }
337 }
338
339 if (commentsLinesLengthLocal <= (currIndex - commentsIndex))
340 {
341 commentsLinesLengthLocal = (currIndex - commentsIndex);
342 }
343
344 breakLine = false;
345
346 for (currIndex = commentsIndex ;
347 (currIndex <= (commentsIndex + commentsLinesLengthLocal)) &&
348 (currIndex < (uint)comments.length()) && !breakLine ;
349 ++currIndex)
350 {
351 breakLine = (comments.at(currIndex) == QLatin1Char('\n')) ? true : false;
352
353 if (breakLine)
354 {
355 newLine.append(QLatin1Char(' '));
356 }
357 else
358 {
359 newLine.append(comments.at(currIndex));
360 }
361 }
362
363 commentsIndex = currIndex; // The line is ended
364
365 if (commentsIndex != (uint)comments.length())
366 {
367 while (!newLine.endsWith(QLatin1Char(' ')))
368 {
369 newLine.truncate(newLine.length() - 1);
370 --commentsIndex;
371 }
372 }
373
374 commentsByLines.prepend(newLine.trimmed());
375 }
376
377 for (int i = 0 ; i < (int)commentsByLines.count() ; ++i)
378 {
379 printInfoText(p, offset, commentsByLines.at(i));
380 }
381 }
382
printTags(QPainter & p,int & offset,QStringList & tags)383 void SlideProperties::printTags(QPainter& p, int& offset, QStringList& tags)
384 {
385 tags.sort();
386
387 QString str = tags.join(QLatin1String(", "));
388
389 if (!str.isEmpty())
390 {
391 printInfoText(p, offset, str, qApp->palette().color(QPalette::Link).name());
392 }
393 }
394
togglePaintEnabled()395 void SlideProperties::togglePaintEnabled()
396 {
397 d->paintEnabled = !d->paintEnabled;
398 update();
399 }
400
401 } // namespace DigikamGenericSlideShowPlugin
402