1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2006-04-19
7 * Description : A tab to display general item information
8 *
9 * Copyright (C) 2006-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2013 by Michael G. Hansen <mike at mghansen dot de>
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 "itempropertiestab.h"
26
27 // Qt includes
28
29 #include <QGridLayout>
30 #include <QStyle>
31 #include <QDir>
32 #include <QFile>
33 #include <QPixmap>
34 #include <QPainter>
35 #include <QPair>
36 #include <QVariant>
37 #include <QApplication>
38 #include <QCollator>
39 #include <QIcon>
40 #include <QLocale>
41 #include <QTime>
42 #include <QtMath>
43
44 // KDE includes
45
46 #include <klocalizedstring.h>
47
48 // Local includes
49
50 #include "itempropertiestxtlabel.h"
51 #include "picklabelwidget.h"
52 #include "colorlabelwidget.h"
53
54 namespace Digikam
55 {
56
57 class Q_DECL_HIDDEN ItemPropertiesTab::Private
58 {
59 public:
60
61 enum Section
62 {
63 FileProperties = 0,
64 ImageProperties,
65 PhotoProperties,
66 VideoProperties,
67 digiKamProperties
68 };
69
70 public:
71
Private()72 explicit Private()
73 : caption (nullptr),
74 pickLabel (nullptr),
75 colorLabel (nullptr),
76 rating (nullptr),
77 tags (nullptr),
78 labelFile (nullptr),
79 labelFolder (nullptr),
80 labelFileModifiedDate (nullptr),
81 labelFileSize (nullptr),
82 labelFileOwner (nullptr),
83 labelFilePermissions (nullptr),
84 labelImageMime (nullptr),
85 labelImageDimensions (nullptr),
86 labelImageRatio (nullptr),
87 labelImageBitDepth (nullptr),
88 labelImageColorMode (nullptr),
89 labelHasSidecar (nullptr),
90 labelPhotoMake (nullptr),
91 labelPhotoModel (nullptr),
92 labelPhotoDateTime (nullptr),
93 labelPhotoLens (nullptr),
94 labelPhotoAperture (nullptr),
95 labelPhotoFocalLength (nullptr),
96 labelPhotoExposureTime (nullptr),
97 labelPhotoSensitivity (nullptr),
98 labelPhotoExposureMode (nullptr),
99 labelPhotoFlash (nullptr),
100 labelPhotoWhiteBalance (nullptr),
101 labelCaption (nullptr),
102 labelTags (nullptr),
103 labelPickLabel (nullptr),
104 labelColorLabel (nullptr),
105 labelRating (nullptr),
106 labelVideoAspectRatio (nullptr),
107 labelVideoDuration (nullptr),
108 labelVideoFrameRate (nullptr),
109 labelVideoVideoCodec (nullptr),
110 labelVideoAudioBitRate (nullptr),
111 labelVideoAudioChannelType(nullptr),
112 labelVideoAudioCodec (nullptr)
113 {
114 }
115
116 DTextLabelName* caption;
117 DTextLabelName* pickLabel;
118 DTextLabelName* colorLabel;
119 DTextLabelName* rating;
120 DTextLabelName* tags;
121
122 DTextLabelValue* labelFile;
123 DTextLabelValue* labelFolder;
124 DTextLabelValue* labelFileModifiedDate;
125 DTextLabelValue* labelFileSize;
126 DTextLabelValue* labelFileOwner;
127 DTextLabelValue* labelFilePermissions;
128
129 DTextLabelValue* labelImageMime;
130 DTextLabelValue* labelImageDimensions;
131 DTextLabelValue* labelImageRatio;
132 DTextLabelValue* labelImageBitDepth;
133 DTextLabelValue* labelImageColorMode;
134 DTextLabelValue* labelHasSidecar;
135
136 DTextLabelValue* labelPhotoMake;
137 DTextLabelValue* labelPhotoModel;
138 DTextLabelValue* labelPhotoDateTime;
139 DTextLabelValue* labelPhotoLens;
140 DTextLabelValue* labelPhotoAperture;
141 DTextLabelValue* labelPhotoFocalLength;
142 DTextLabelValue* labelPhotoExposureTime;
143 DTextLabelValue* labelPhotoSensitivity;
144 DTextLabelValue* labelPhotoExposureMode;
145 DTextLabelValue* labelPhotoFlash;
146 DTextLabelValue* labelPhotoWhiteBalance;
147
148 DTextLabelValue* labelCaption;
149 DTextLabelValue* labelTags;
150 DTextLabelValue* labelPickLabel;
151 DTextLabelValue* labelColorLabel;
152 DTextLabelValue* labelRating;
153
154 DTextLabelValue* labelVideoAspectRatio;
155 DTextLabelValue* labelVideoDuration;
156 DTextLabelValue* labelVideoFrameRate;
157 DTextLabelValue* labelVideoVideoCodec;
158 DTextLabelValue* labelVideoAudioBitRate;
159 DTextLabelValue* labelVideoAudioChannelType;
160 DTextLabelValue* labelVideoAudioCodec;
161 };
162
ItemPropertiesTab(QWidget * const parent)163 ItemPropertiesTab::ItemPropertiesTab(QWidget* const parent)
164 : DExpanderBox(parent),
165 d (new Private)
166 {
167 setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
168 setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
169
170 // --------------------------------------------------
171
172 const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
173
174 QWidget* const w1 = new QWidget(this);
175 QGridLayout* const glay1 = new QGridLayout(w1);
176
177 DTextLabelName* const file = new DTextLabelName(i18nc("@label: item properties", "File: "), w1);
178 DTextLabelName* const folder = new DTextLabelName(i18nc("@label: item properties", "Folder: "), w1);
179 DTextLabelName* const modifiedDate = new DTextLabelName(i18nc("@label: item properties", "Date: "), w1);
180 DTextLabelName* const size = new DTextLabelName(i18nc("@label: item properties", "Size: "), w1);
181 DTextLabelName* const owner = new DTextLabelName(i18nc("@label: item properties", "Owner: "), w1);
182 DTextLabelName* const permissions = new DTextLabelName(i18nc("@label: item properties", "Permissions: "), w1);
183
184 d->labelFile = new DTextLabelValue(QString(), w1);
185 d->labelFolder = new DTextLabelValue(QString(), w1);
186 d->labelFileModifiedDate = new DTextLabelValue(QString(), w1);
187 d->labelFileSize = new DTextLabelValue(QString(), w1);
188 d->labelFileOwner = new DTextLabelValue(QString(), w1);
189 d->labelFilePermissions = new DTextLabelValue(QString(), w1);
190
191 glay1->addWidget(file, 0, 0, 1, 1);
192 glay1->addWidget(d->labelFile, 0, 1, 1, 1);
193 glay1->addWidget(folder, 1, 0, 1, 1);
194 glay1->addWidget(d->labelFolder, 1, 1, 1, 1);
195 glay1->addWidget(modifiedDate, 2, 0, 1, 1);
196 glay1->addWidget(d->labelFileModifiedDate, 2, 1, 1, 1);
197 glay1->addWidget(size, 3, 0, 1, 1);
198 glay1->addWidget(d->labelFileSize, 3, 1, 1, 1);
199 glay1->addWidget(owner, 4, 0, 1, 1);
200 glay1->addWidget(d->labelFileOwner, 4, 1, 1, 1);
201 glay1->addWidget(permissions, 5, 0, 1, 1);
202 glay1->addWidget(d->labelFilePermissions, 5, 1, 1, 1);
203 glay1->setContentsMargins(spacing, spacing, spacing, spacing);
204 glay1->setColumnStretch(0, 10);
205 glay1->setColumnStretch(1, 25);
206 glay1->setSpacing(0);
207
208 insertItem(ItemPropertiesTab::Private::FileProperties,
209 w1, QIcon::fromTheme(QLatin1String("dialog-information")),
210 i18nc("@title: item properties", "File Properties"), QLatin1String("FileProperties"), true);
211
212 // --------------------------------------------------
213
214 QWidget* const w2 = new QWidget(this);
215 QGridLayout* const glay2 = new QGridLayout(w2);
216
217 DTextLabelName* const mime = new DTextLabelName(i18nc("@label: item properties", "Type: "), w2);
218 DTextLabelName* const dimensions = new DTextLabelName(i18nc("@label: item properties", "Dimensions: "), w2);
219 DTextLabelName* const ratio = new DTextLabelName(i18nc("@label: item properties", "Aspect Ratio: "), w2);
220 DTextLabelName* const bitDepth = new DTextLabelName(i18nc("@label: item properties", "Bit depth: "), w2);
221 DTextLabelName* const colorMode = new DTextLabelName(i18nc("@label: item properties", "Color mode: "), w2);
222 DTextLabelName* const hasSidecar = new DTextLabelName(i18nc("@label: item properties", "Sidecar: "), w2);
223
224 d->labelImageMime = new DTextLabelValue(QString(), w2);
225 d->labelImageDimensions = new DTextLabelValue(QString(), w2);
226 d->labelImageRatio = new DTextLabelValue(QString(), w2);
227 d->labelImageBitDepth = new DTextLabelValue(QString(), w2);
228 d->labelImageColorMode = new DTextLabelValue(QString(), w2);
229 d->labelHasSidecar = new DTextLabelValue(QString(), w2);
230
231 glay2->addWidget(mime, 0, 0, 1, 1);
232 glay2->addWidget(d->labelImageMime, 0, 1, 1, 1);
233 glay2->addWidget(dimensions, 1, 0, 1, 1);
234 glay2->addWidget(d->labelImageDimensions, 1, 1, 1, 1);
235 glay2->addWidget(ratio, 2, 0, 1, 1);
236 glay2->addWidget(d->labelImageRatio, 2, 1, 1, 1);
237 glay2->addWidget(bitDepth, 3, 0, 1, 1);
238 glay2->addWidget(d->labelImageBitDepth, 3, 1, 1, 1);
239 glay2->addWidget(colorMode, 4, 0, 1, 1);
240 glay2->addWidget(d->labelImageColorMode, 4, 1, 1, 1);
241 glay2->addWidget(hasSidecar, 5, 0, 1, 1);
242 glay2->addWidget(d->labelHasSidecar, 5, 1, 1, 1);
243 glay2->setContentsMargins(spacing, spacing, spacing, spacing);
244 glay2->setColumnStretch(0, 10);
245 glay2->setColumnStretch(1, 25);
246 glay2->setSpacing(0);
247
248 insertItem(ItemPropertiesTab::Private::ImageProperties,
249 w2, QIcon::fromTheme(QLatin1String("view-preview")),
250 i18nc("@title: item properties", "Item Properties"), QLatin1String("ItemProperties"), true);
251
252 // --------------------------------------------------
253
254 QWidget* const w3 = new QWidget(this);
255 QGridLayout* const glay3 = new QGridLayout(w3);
256
257 DTextLabelName* const make = new DTextLabelName(i18nc("@label: item properties", "Make: "), w3);
258 DTextLabelName* const model = new DTextLabelName(i18nc("@label: item properties", "Model: "), w3);
259 DTextLabelName* const photoDate = new DTextLabelName(i18nc("@label: item properties", "Created: "), w3);
260 DTextLabelName* const lens = new DTextLabelName(i18nc("@label: item properties", "Lens: "), w3);
261 DTextLabelName* const aperture = new DTextLabelName(i18nc("@label: item properties", "Aperture: "), w3);
262 DTextLabelName* const focalLength = new DTextLabelName(i18nc("@label: item properties", "Focal: "), w3);
263 DTextLabelName* const exposureTime = new DTextLabelName(i18nc("@label: item properties", "Exposure: "), w3);
264 DTextLabelName* const sensitivity = new DTextLabelName(i18nc("@label: item properties", "Sensitivity: "), w3);
265 DTextLabelName* const exposureMode = new DTextLabelName(i18nc("@label: item properties", "Mode/Program: "), w3);
266 DTextLabelName* const flash = new DTextLabelName(i18nc("@label: item properties", "Flash: "), w3);
267 DTextLabelName* const whiteBalance = new DTextLabelName(i18nc("@label: item properties", "White balance: "), w3);
268
269 d->labelPhotoMake = new DTextLabelValue(QString(), w3);
270 d->labelPhotoModel = new DTextLabelValue(QString(), w3);
271 d->labelPhotoDateTime = new DTextLabelValue(QString(), w3);
272 d->labelPhotoLens = new DTextLabelValue(QString(), w3);
273 d->labelPhotoAperture = new DTextLabelValue(QString(), w3);
274 d->labelPhotoFocalLength = new DTextLabelValue(QString(), w3);
275 d->labelPhotoExposureTime = new DTextLabelValue(QString(), w3);
276 d->labelPhotoSensitivity = new DTextLabelValue(QString(), w3);
277 d->labelPhotoExposureMode = new DTextLabelValue(QString(), w3);
278 d->labelPhotoFlash = new DTextLabelValue(QString(), w3);
279 d->labelPhotoWhiteBalance = new DTextLabelValue(QString(), w3);
280
281 glay3->addWidget(make, 0, 0, 1, 1);
282 glay3->addWidget(d->labelPhotoMake, 0, 1, 1, 1);
283 glay3->addWidget(model, 1, 0, 1, 1);
284 glay3->addWidget(d->labelPhotoModel, 1, 1, 1, 1);
285 glay3->addWidget(photoDate, 2, 0, 1, 1);
286 glay3->addWidget(d->labelPhotoDateTime, 2, 1, 1, 1);
287 glay3->addWidget(lens, 3, 0, 1, 1);
288 glay3->addWidget(d->labelPhotoLens, 3, 1, 1, 1);
289 glay3->addWidget(aperture, 4, 0, 1, 1);
290 glay3->addWidget(d->labelPhotoAperture, 4, 1, 1, 1);
291 glay3->addWidget(focalLength, 5, 0, 1, 1);
292 glay3->addWidget(d->labelPhotoFocalLength, 5, 1, 1, 1);
293 glay3->addWidget(exposureTime, 6, 0, 1, 1);
294 glay3->addWidget(d->labelPhotoExposureTime, 6, 1, 1, 1);
295 glay3->addWidget(sensitivity, 7, 0, 1, 1);
296 glay3->addWidget(d->labelPhotoSensitivity, 7, 1, 1, 1);
297 glay3->addWidget(exposureMode, 8, 0, 1, 1);
298 glay3->addWidget(d->labelPhotoExposureMode, 8, 1, 1, 1);
299 glay3->addWidget(flash, 9, 0, 1, 1);
300 glay3->addWidget(d->labelPhotoFlash, 9, 1, 1, 1);
301 glay3->addWidget(whiteBalance, 10, 0, 1, 1);
302 glay3->addWidget(d->labelPhotoWhiteBalance, 10, 1, 1, 1);
303 glay3->setContentsMargins(spacing, spacing, spacing, spacing);
304 glay3->setColumnStretch(0, 10);
305 glay3->setColumnStretch(1, 25);
306 glay3->setSpacing(0);
307
308 insertItem(ItemPropertiesTab::Private::PhotoProperties,
309 w3, QIcon::fromTheme(QLatin1String("camera-photo")),
310 i18nc("@title: item properties", "Photograph Properties"), QLatin1String("PhotographProperties"), true);
311
312 // --------------------------------------------------
313
314 QWidget* const w4 = new QWidget(this);
315 QGridLayout* const glay4 = new QGridLayout(w4);
316
317 DTextLabelName* const aspectRatio = new DTextLabelName(i18nc("@label: item properties", "Aspect Ratio: "), w4);
318 DTextLabelName* const duration = new DTextLabelName(i18nc("@label: item properties", "Duration: "), w4);
319 DTextLabelName* const frameRate = new DTextLabelName(i18nc("@label: item properties", "Frame Rate: "), w4);
320 DTextLabelName* const videoCodec = new DTextLabelName(i18nc("@label: item properties", "Video Codec: "), w4);
321 DTextLabelName* const audioBitRate = new DTextLabelName(i18nc("@label: item properties", "Audio Bit Rate: "), w4);
322 DTextLabelName* const audioChannelType = new DTextLabelName(i18nc("@label: item properties", "Audio Channel Type: "), w4);
323 DTextLabelName* const audioCodec = new DTextLabelName(i18nc("@label: item properties", "Audio Codec: "), w4);
324
325 d->labelVideoAspectRatio = new DTextLabelValue(QString(), w4);
326 d->labelVideoDuration = new DTextLabelValue(QString(), w4);
327 d->labelVideoFrameRate = new DTextLabelValue(QString(), w4);
328 d->labelVideoVideoCodec = new DTextLabelValue(QString(), w4);
329 d->labelVideoAudioBitRate = new DTextLabelValue(QString(), w4);
330 d->labelVideoAudioChannelType = new DTextLabelValue(QString(), w4);
331 d->labelVideoAudioCodec = new DTextLabelValue(QString(), w4);
332
333 glay4->addWidget(aspectRatio, 0, 0, 1, 1);
334 glay4->addWidget(d->labelVideoAspectRatio, 0, 1, 1, 1);
335 glay4->addWidget(duration, 1, 0, 1, 1);
336 glay4->addWidget(d->labelVideoDuration, 1, 1, 1, 1);
337 glay4->addWidget(frameRate, 2, 0, 1, 1);
338 glay4->addWidget(d->labelVideoFrameRate, 2, 1, 1, 1);
339 glay4->addWidget(videoCodec, 3, 0, 1, 1);
340 glay4->addWidget(d->labelVideoVideoCodec, 3, 1, 1, 1);
341 glay4->addWidget(audioBitRate, 4, 0, 1, 1);
342 glay4->addWidget(d->labelVideoAudioBitRate, 4, 1, 1, 1);
343 glay4->addWidget(audioChannelType, 5, 0, 1, 1);
344 glay4->addWidget(d->labelVideoAudioChannelType, 5, 1, 1, 1);
345 glay4->addWidget(audioCodec, 6, 0, 1, 1);
346 glay4->addWidget(d->labelVideoAudioCodec, 6, 1, 1, 1);
347 glay4->setContentsMargins(spacing, spacing, spacing, spacing);
348 glay4->setColumnStretch(0, 10);
349 glay4->setColumnStretch(1, 25);
350 glay4->setSpacing(0);
351
352 insertItem(ItemPropertiesTab::Private::VideoProperties,
353 w4, QIcon::fromTheme(QLatin1String("video-x-generic")),
354 i18nc("@title: item properties", "Audio/Video Properties"), QLatin1String("VideoProperties"), true);
355
356 // --------------------------------------------------
357
358 QWidget* const w5 = new QWidget(this);
359 QGridLayout* const glay5 = new QGridLayout(w5);
360
361 d->caption = new DTextLabelName(i18nc("@label: item properties", "Caption: "), w5);
362 d->pickLabel = new DTextLabelName(i18nc("@label: item properties", "Pick label: "), w5);
363 d->colorLabel = new DTextLabelName(i18nc("@label: item properties", "Color label: "), w5);
364 d->rating = new DTextLabelName(i18nc("@label: item properties", "Rating: "), w5);
365 d->tags = new DTextLabelName(i18nc("@label: item properties", "Tags: "), w5);
366
367 d->labelCaption = new DTextLabelValue(QString(), w5);
368 d->labelPickLabel = new DTextLabelValue(QString(), w5);
369 d->labelColorLabel = new DTextLabelValue(QString(), w5);
370 d->labelRating = new DTextLabelValue(QString(), w5);
371 d->labelTags = new DTextLabelValue(QString(), w5);
372 d->labelTags->setElideMode(Qt::ElideLeft);
373
374 glay5->addWidget(d->caption, 0, 0, 1, 1);
375 glay5->addWidget(d->labelCaption, 0, 1, 1, 1);
376 glay5->addWidget(d->tags, 1, 0, 1, 1);
377 glay5->addWidget(d->labelTags, 1, 1, 1, 1);
378 glay5->addWidget(d->pickLabel, 2, 0, 1, 1);
379 glay5->addWidget(d->labelPickLabel, 2, 1, 1, 1);
380 glay5->addWidget(d->colorLabel, 3, 0, 1, 1);
381 glay5->addWidget(d->labelColorLabel, 3, 1, 1, 1);
382 glay5->addWidget(d->rating, 4, 0, 1, 1);
383 glay5->addWidget(d->labelRating, 4, 1, 1, 1);
384 glay5->setContentsMargins(spacing, spacing, spacing, spacing);
385 glay5->setColumnStretch(0, 10);
386 glay5->setColumnStretch(1, 25);
387 glay5->setSpacing(0);
388
389 insertItem(ItemPropertiesTab::Private::digiKamProperties,
390 w5, QIcon::fromTheme(QLatin1String("edit-text-frame-update")),
391 i18nc("@title: item properties", "digiKam Properties"), QLatin1String("DigikamProperties"), true);
392
393 // --------------------------------------------------
394
395 addStretch();
396 }
397
~ItemPropertiesTab()398 ItemPropertiesTab::~ItemPropertiesTab()
399 {
400 delete d;
401 }
402
setCurrentURL(const QUrl & url)403 void ItemPropertiesTab::setCurrentURL(const QUrl& url)
404 {
405 if (url.isEmpty())
406 {
407 d->labelFile->setAdjustedText();
408 d->labelFolder->setAdjustedText();
409 d->labelFileModifiedDate->setAdjustedText();
410 d->labelFileSize->setAdjustedText();
411 d->labelFileOwner->setAdjustedText();
412 d->labelFilePermissions->setAdjustedText();
413
414 d->labelImageMime->setAdjustedText();
415 d->labelImageDimensions->setAdjustedText();
416 d->labelImageRatio->setAdjustedText();
417 d->labelImageBitDepth->setAdjustedText();
418 d->labelImageColorMode->setAdjustedText();
419 d->labelHasSidecar->setAdjustedText();
420
421 d->labelPhotoMake->setAdjustedText();
422 d->labelPhotoModel->setAdjustedText();
423 d->labelPhotoDateTime->setAdjustedText();
424 d->labelPhotoLens->setAdjustedText();
425 d->labelPhotoAperture->setAdjustedText();
426 d->labelPhotoFocalLength->setAdjustedText();
427 d->labelPhotoExposureTime->setAdjustedText();
428 d->labelPhotoSensitivity->setAdjustedText();
429 d->labelPhotoExposureMode->setAdjustedText();
430 d->labelPhotoFlash->setAdjustedText();
431 d->labelPhotoWhiteBalance->setAdjustedText();
432
433 d->labelCaption->setAdjustedText();
434 d->labelPickLabel->setAdjustedText();
435 d->labelColorLabel->setAdjustedText();
436 d->labelRating->setAdjustedText();
437 d->labelTags->setAdjustedText();
438
439 d->labelVideoAspectRatio->setAdjustedText();
440 d->labelVideoDuration->setAdjustedText();
441 d->labelVideoFrameRate->setAdjustedText();
442 d->labelVideoVideoCodec->setAdjustedText();
443 d->labelVideoAudioBitRate->setAdjustedText();
444 d->labelVideoAudioChannelType->setAdjustedText();
445 d->labelVideoAudioCodec->setAdjustedText();
446
447 setEnabled(false);
448 return;
449 }
450
451 setEnabled(true);
452
453 d->labelFile->setAdjustedText(url.fileName());
454 d->labelFolder->setAdjustedText(QDir::toNativeSeparators(url.adjusted(QUrl::RemoveFilename |
455 QUrl::StripTrailingSlash).toLocalFile()));
456 }
457
setPhotoInfoDisable(const bool b)458 void ItemPropertiesTab::setPhotoInfoDisable(const bool b)
459 {
460 if (b)
461 {
462 widget(ItemPropertiesTab::Private::PhotoProperties)->hide();
463 }
464 else
465 {
466 widget(ItemPropertiesTab::Private::PhotoProperties)->show();
467 }
468 }
469
setVideoInfoDisable(const bool b)470 void ItemPropertiesTab::setVideoInfoDisable(const bool b)
471 {
472 if (b)
473 {
474 widget(ItemPropertiesTab::Private::VideoProperties)->hide();
475 }
476 else
477 {
478 widget(ItemPropertiesTab::Private::VideoProperties)->show();
479 }
480 }
481
setFileModifiedDate(const QString & str)482 void ItemPropertiesTab::setFileModifiedDate(const QString& str)
483 {
484 d->labelFileModifiedDate->setAdjustedText(str);
485 }
486
setFileSize(const QString & str)487 void ItemPropertiesTab::setFileSize(const QString& str)
488 {
489 d->labelFileSize->setAdjustedText(str);
490 }
491
setFileOwner(const QString & str)492 void ItemPropertiesTab::setFileOwner(const QString& str)
493 {
494 d->labelFileOwner->setAdjustedText(str);
495 }
496
setFilePermissions(const QString & str)497 void ItemPropertiesTab::setFilePermissions(const QString& str)
498 {
499 d->labelFilePermissions->setAdjustedText(str);
500 }
501
setImageMime(const QString & str)502 void ItemPropertiesTab::setImageMime(const QString& str)
503 {
504 d->labelImageMime->setAdjustedText(str);
505 }
506
setItemDimensions(const QString & str)507 void ItemPropertiesTab::setItemDimensions(const QString& str)
508 {
509 d->labelImageDimensions->setAdjustedText(str);
510 }
511
setImageRatio(const QString & str)512 void ItemPropertiesTab::setImageRatio(const QString& str)
513 {
514 d->labelImageRatio->setAdjustedText(str);
515 }
516
setImageBitDepth(const QString & str)517 void ItemPropertiesTab::setImageBitDepth(const QString& str)
518 {
519 d->labelImageBitDepth->setAdjustedText(str);
520 }
521
setImageColorMode(const QString & str)522 void ItemPropertiesTab::setImageColorMode(const QString& str)
523 {
524 d->labelImageColorMode->setAdjustedText(str);
525 }
526
setHasSidecar(const QString & str)527 void ItemPropertiesTab::setHasSidecar(const QString& str)
528 {
529 d->labelHasSidecar->setAdjustedText(str);
530 }
531
setPhotoMake(const QString & str)532 void ItemPropertiesTab::setPhotoMake(const QString& str)
533 {
534 d->labelPhotoMake->setAdjustedText(str);
535 }
536
setPhotoModel(const QString & str)537 void ItemPropertiesTab::setPhotoModel(const QString& str)
538 {
539 d->labelPhotoModel->setAdjustedText(str);
540 }
541
setPhotoDateTime(const QString & str)542 void ItemPropertiesTab::setPhotoDateTime(const QString& str)
543 {
544 d->labelPhotoDateTime->setAdjustedText(str);
545 }
546
setPhotoLens(const QString & str)547 void ItemPropertiesTab::setPhotoLens(const QString& str)
548 {
549 d->labelPhotoLens->setAdjustedText(str);
550 }
551
setPhotoAperture(const QString & str)552 void ItemPropertiesTab::setPhotoAperture(const QString& str)
553 {
554 d->labelPhotoAperture->setAdjustedText(str);
555 }
556
setPhotoFocalLength(const QString & str)557 void ItemPropertiesTab::setPhotoFocalLength(const QString& str)
558 {
559 d->labelPhotoFocalLength->setAdjustedText(str);
560 }
561
setPhotoExposureTime(const QString & str)562 void ItemPropertiesTab::setPhotoExposureTime(const QString& str)
563 {
564 d->labelPhotoExposureTime->setAdjustedText(str);
565 }
566
setPhotoSensitivity(const QString & str)567 void ItemPropertiesTab::setPhotoSensitivity(const QString& str)
568 {
569 d->labelPhotoSensitivity->setAdjustedText(str);
570 }
571
setPhotoExposureMode(const QString & str)572 void ItemPropertiesTab::setPhotoExposureMode(const QString& str)
573 {
574 d->labelPhotoExposureMode->setAdjustedText(str);
575 }
576
setPhotoFlash(const QString & str)577 void ItemPropertiesTab::setPhotoFlash(const QString& str)
578 {
579 d->labelPhotoFlash->setAdjustedText(str);
580 }
581
setPhotoWhiteBalance(const QString & str)582 void ItemPropertiesTab::setPhotoWhiteBalance(const QString& str)
583 {
584 d->labelPhotoWhiteBalance->setAdjustedText(str);
585 }
586
showOrHideCaptionAndTags()587 void ItemPropertiesTab::showOrHideCaptionAndTags()
588 {
589 bool hasCaption = !d->labelCaption->adjustedText().isEmpty();
590 bool hasPickLabel = !d->labelPickLabel->adjustedText().isEmpty();
591 bool hasColorLabel = !d->labelColorLabel->adjustedText().isEmpty();
592 bool hasRating = !d->labelRating->adjustedText().isEmpty();
593 bool hasTags = !d->labelTags->adjustedText().isEmpty();
594
595 d->caption->setVisible(hasCaption);
596 d->labelCaption->setVisible(hasCaption);
597 d->pickLabel->setVisible(hasPickLabel);
598 d->labelPickLabel->setVisible(hasPickLabel);
599 d->colorLabel->setVisible(hasColorLabel);
600 d->labelColorLabel->setVisible(hasColorLabel);
601 d->rating->setVisible(hasRating);
602 d->labelRating->setVisible(hasRating);
603 d->tags->setVisible(hasTags);
604 d->labelTags->setVisible(hasTags);
605
606 widget(ItemPropertiesTab::Private::digiKamProperties)->setVisible(hasCaption ||
607 hasRating ||
608 hasTags ||
609 hasPickLabel ||
610 hasColorLabel);
611 }
612
setCaption(const QString & str)613 void ItemPropertiesTab::setCaption(const QString& str)
614 {
615 d->labelCaption->setAdjustedText(str);
616 }
617
setColorLabel(int colorId)618 void ItemPropertiesTab::setColorLabel(int colorId)
619 {
620 if (colorId == NoColorLabel)
621 {
622 d->labelColorLabel->setAdjustedText(QString());
623 }
624 else
625 {
626 d->labelColorLabel->setAdjustedText(ColorLabelWidget::labelColorName((ColorLabel)colorId));
627 }
628 }
629
setPickLabel(int pickId)630 void ItemPropertiesTab::setPickLabel(int pickId)
631 {
632 if (pickId == NoPickLabel)
633 {
634 d->labelPickLabel->setAdjustedText(QString());
635 }
636 else
637 {
638 d->labelPickLabel->setAdjustedText(PickLabelWidget::labelPickName((PickLabel)pickId));
639 }
640 }
641
setRating(int rating)642 void ItemPropertiesTab::setRating(int rating)
643 {
644 QString str;
645
646 if ((rating > RatingMin) && (rating <= RatingMax))
647 {
648 str = QLatin1Char(' ');
649
650 for (int i = 0 ; i < rating ; ++i)
651 {
652 str += QChar(0x2730);
653 str += QLatin1Char(' ');
654 }
655 }
656
657 d->labelRating->setAdjustedText(str);
658 }
659
setVideoAspectRatio(const QString & str)660 void ItemPropertiesTab::setVideoAspectRatio(const QString& str)
661 {
662 d->labelVideoAspectRatio->setAdjustedText(str);
663 }
664
setVideoAudioBitRate(const QString & str)665 void ItemPropertiesTab::setVideoAudioBitRate(const QString& str)
666 {
667 // use string given as parameter by default because it contains the value for "unavailable" if needed
668
669 QString audioBitRateString = str;
670 bool ok = false;
671 const int audioBitRateInt = str.toInt(&ok);
672
673 if (ok)
674 {
675 audioBitRateString = QLocale().toString(audioBitRateInt);
676 }
677
678 d->labelVideoAudioBitRate->setAdjustedText(audioBitRateString);
679 }
680
setVideoAudioChannelType(const QString & str)681 void ItemPropertiesTab::setVideoAudioChannelType(const QString& str)
682 {
683 d->labelVideoAudioChannelType->setAdjustedText(str);
684 }
685
setVideoAudioCodec(const QString & str)686 void ItemPropertiesTab::setVideoAudioCodec(const QString& str)
687 {
688 d->labelVideoAudioCodec->setAdjustedText(str);
689 }
690
setVideoDuration(const QString & str)691 void ItemPropertiesTab::setVideoDuration(const QString& str)
692 {
693 // duration is given as a string in milliseconds
694 // use string given as parameter by default because it contains the value for "unavailable" if needed
695
696 QString durationString = str;
697 bool ok = false;
698 const int durationVal = str.toInt(&ok);
699
700 if (ok)
701 {
702 unsigned int r, d, h, m, s, f;
703 r = qAbs(durationVal);
704 d = r / 86400000;
705 r = r % 86400000;
706 h = r / 3600000;
707 r = r % 3600000;
708 m = r / 60000;
709 r = r % 60000;
710 s = r / 1000;
711 f = r % 1000;
712
713 durationString = QString().asprintf("%d.%02d:%02d:%02d.%03d", d, h, m, s, f);
714 }
715
716 d->labelVideoDuration->setAdjustedText(durationString);
717 }
718
setVideoFrameRate(const QString & str)719 void ItemPropertiesTab::setVideoFrameRate(const QString& str)
720 {
721 // use string given as parameter by default because it contains the value for "unavailable" if needed
722
723 QString frameRateString = str;
724 bool ok;
725 const double frameRateDouble = str.toDouble(&ok);
726
727 if (ok)
728 {
729 frameRateString = QLocale().toString(frameRateDouble) + i18nc("@info: item properties", " fps");
730 }
731
732 d->labelVideoFrameRate->setAdjustedText(frameRateString);
733 }
734
setVideoVideoCodec(const QString & str)735 void ItemPropertiesTab::setVideoVideoCodec(const QString& str)
736 {
737 d->labelVideoVideoCodec->setAdjustedText(str);
738 }
739
setTags(const QStringList & tagPaths,const QStringList & tagNames)740 void ItemPropertiesTab::setTags(const QStringList& tagPaths, const QStringList& tagNames)
741 {
742 Q_UNUSED(tagNames);
743 d->labelTags->setAdjustedText(shortenedTagPaths(tagPaths).join(QLatin1Char('\n')));
744 }
745
746 typedef QPair<QString, QVariant> PathValuePair;
747
naturalLessThan(const PathValuePair & a,const PathValuePair & b)748 static bool naturalLessThan(const PathValuePair& a, const PathValuePair& b)
749 {
750 return (QCollator().compare(a.first, b.first) < 0);
751 }
752
shortenedTagPaths(const QStringList & tagPaths,QList<QVariant> * identifiers)753 QStringList ItemPropertiesTab::shortenedTagPaths(const QStringList& tagPaths, QList<QVariant>* identifiers)
754 {
755 QList<PathValuePair> tagsSorted;
756
757 if (identifiers)
758 {
759 for (int i = 0 ; i < tagPaths.size() ; ++i)
760 {
761 tagsSorted << PathValuePair(tagPaths.at(i), (*identifiers).at(i));
762 }
763 }
764 else
765 {
766 for (int i = 0 ; i < tagPaths.size() ; ++i)
767 {
768 tagsSorted << PathValuePair(tagPaths.at(i), QVariant());
769 }
770 }
771
772 std::stable_sort(tagsSorted.begin(), tagsSorted.end(), naturalLessThan);
773
774 if (identifiers)
775 {
776 identifiers->clear();
777 }
778
779 QStringList tagsShortened;
780 QString previous;
781
782 foreach (const PathValuePair& pair, tagsSorted)
783 {
784 const QString& tagPath = pair.first;
785 QString shortenedPath = tagPath;
786 QStringList currentPath = tagPath.split(QLatin1Char('/'), QString::SkipEmptyParts);
787 QStringList previousPath = previous.split(QLatin1Char('/'), QString::SkipEmptyParts);
788 int depth;
789
790 for (depth = 0 ; (depth < currentPath.size()) && (depth < previousPath.size()) ; ++depth)
791 {
792 if (currentPath.at(depth) != previousPath.at(depth))
793 {
794 break;
795 }
796 }
797
798 if (depth)
799 {
800 QString indent;
801 indent.fill(QLatin1Char(' '), qMin(depth, 5));
802 /*
803 indent += QChar(0x2026);
804 */
805 shortenedPath = indent + tagPath.section(QLatin1Char('/'), depth);
806 }
807
808 shortenedPath.replace(QLatin1Char('/'), QLatin1String(" / "));
809 tagsShortened << shortenedPath;
810 previous = tagPath;
811
812 if (identifiers)
813 {
814 (*identifiers) << pair.second;
815 }
816 }
817
818 return tagsShortened;
819 }
820
shortenedMakeInfo(QString & make)821 void ItemPropertiesTab::shortenedMakeInfo(QString& make)
822 {
823 make.remove(QLatin1String(" CORPORATION"), Qt::CaseInsensitive); // from Nikon, Pentax, and Olympus
824 make.remove(QLatin1String("EASTMAN "), Qt::CaseInsensitive); // from Kodak
825 make.remove(QLatin1String(" COMPANY"), Qt::CaseInsensitive); // from Kodak
826 make.remove(QLatin1String(" OPTICAL CO.,LTD"), Qt::CaseInsensitive); // from Olympus
827 make.remove(QLatin1String(" IMAGING CORP."), Qt::CaseInsensitive); // from Olympus
828 make.remove(QLatin1String(" Techwin co.,Ltd."), Qt::CaseInsensitive); // from Samsung
829 make.remove(QLatin1String(" Co.,Ltd."), Qt::CaseInsensitive); // from Minolta
830 make.remove(QLatin1String(" Electric Co.,Ltd."), Qt::CaseInsensitive); // from Sanyo
831 make.remove(QLatin1String(" Electric Co.,Ltd"), Qt::CaseInsensitive); // from Sanyo
832 }
833
shortenedModelInfo(QString & model)834 void ItemPropertiesTab::shortenedModelInfo(QString& model)
835 {
836 model.remove(QLatin1String("Canon "), Qt::CaseInsensitive);
837 model.remove(QLatin1String("NIKON "), Qt::CaseInsensitive);
838 model.remove(QLatin1String("PENTAX "), Qt::CaseInsensitive);
839 model.remove(QLatin1String(" DIGITAL"), Qt::CaseInsensitive); // from Canon
840 model.remove(QLatin1String("KODAK "), Qt::CaseInsensitive);
841 model.remove(QLatin1String(" CAMERA"), Qt::CaseInsensitive); // from Kodak
842 }
843
844 /**
845 * Find rational approximation to given real number
846 *
847 * val : double value to convert as humain readable fraction
848 * num : fraction numerator
849 * den : fraction denominator
850 * maxden : the maximum denominator allowed
851 *
852 * This function return approximation error of the fraction
853 *
854 * Based on the theory of continued fractions
855 * if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
856 * Then best approximation is found by truncating this series
857 * wwith some adjustments in the last term.
858 *
859 * Note the fraction can be recovered as the first column of the matrix
860 * ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
861 * ( 1 0 ) ( 1 0 ) ( 1 0 )
862 * Instead of keeping the sequence of continued fraction terms,
863 * we just keep the last partial product of these matrices.
864 *
865 * Details: stackoverflow.com/questions/95727/how-to-convert-floats-to-human-readable-fractions
866 *
867 */
doubleToHumanReadableFraction(double val,long * num,long * den,long maxden)868 double ItemPropertiesTab::doubleToHumanReadableFraction(double val, long* num, long* den, long maxden)
869 {
870 double x = val;
871 long m[2][2];
872 long ai;
873
874 // Initialize matrix
875
876 m[0][0] = m[1][1] = 1;
877 m[0][1] = m[1][0] = 0;
878
879 // Loop finding terms until denominator gets too big
880
881 while (m[1][0] * (ai = (long)x) + m[1][1] <= maxden)
882 {
883 long t = m[0][0] * ai + m[0][1];
884 m[0][1] = m[0][0];
885 m[0][0] = t;
886 t = m[1][0] * ai + m[1][1];
887 m[1][1] = m[1][0];
888 m[1][0] = t;
889
890 if (x == (double)ai)
891 {
892 break; // division by zero
893 }
894
895 x = 1 / (x - (double)ai);
896
897 if (x > (double)0x7FFFFFFF)
898 {
899 break; // representation failure
900 }
901 }
902
903 // Now remaining x is between 0 and 1/ai
904 // Approx as either 0 or 1/m where m is max that will fit in maxden
905
906 *num = m[0][0];
907 *den = m[1][0];
908
909 // Return approximation error
910
911 return (val - ((double)m[0][0] / (double)m[1][0]));
912 }
913
aspectRatioToString(int width,int height,QString & arString)914 bool ItemPropertiesTab::aspectRatioToString(int width, int height, QString& arString)
915 {
916 if ((width == 0) || (height == 0))
917 {
918 return false;
919 }
920
921 double ratio = (double)qMax(width, height) / (double)qMin(width, height);
922 long num = 0;
923 long den = 0;
924
925 doubleToHumanReadableFraction(ratio, &num, &den, 10);
926
927 double aratio = (double)qMax(num, den) / (double)qMin(num, den);
928
929 arString = i18nc("@info: width : height (Aspect Ratio)", "%1:%2 (%3)",
930 (width > height) ? num : den,
931 (width > height) ? den : num,
932 QLocale().toString(aratio, 'g', 2));
933
934 return true;
935 }
936
permissionsString(const QFileInfo & fi)937 QString ItemPropertiesTab::permissionsString(const QFileInfo& fi)
938 {
939 QString str;
940 QFile::Permissions perms = fi.permissions();
941
942 str.append(fi.isSymLink() ? QLatin1String("l") : QLatin1String("-"));
943
944 str.append((perms & QFileDevice::ReadOwner) ? QLatin1String("r") : QLatin1String("-"));
945 str.append((perms & QFileDevice::WriteOwner) ? QLatin1String("w") : QLatin1String("-"));
946 str.append((perms & QFileDevice::ExeOwner) ? QLatin1String("x") : QLatin1String("-"));
947
948 str.append((perms & QFileDevice::ReadGroup) ? QLatin1String("r") : QLatin1String("-"));
949 str.append((perms & QFileDevice::WriteGroup) ? QLatin1String("w") : QLatin1String("-"));
950 str.append((perms & QFileDevice::ExeGroup) ? QLatin1String("x") : QLatin1String("-"));
951
952 str.append((perms & QFileDevice::ReadOther) ? QLatin1String("r") : QLatin1String("-"));
953 str.append((perms & QFileDevice::WriteOther) ? QLatin1String("w") : QLatin1String("-"));
954 str.append((perms & QFileDevice::ExeOther) ? QLatin1String("x") : QLatin1String("-"));
955
956 return str;
957 }
958
humanReadableBytesCount(qint64 bytes,bool si)959 QString ItemPropertiesTab::humanReadableBytesCount(qint64 bytes, bool si)
960 {
961 int unit = si ? 1000 : 1024;
962 QString byteStr = i18nc("@info: unit file size in bytes", "B");
963 QString ret = QString::number(bytes);
964
965 if (bytes >= unit)
966 {
967 int exp = (int)(qLn(bytes) / qLn(unit));
968 QString pre = QString(si ? QLatin1String("kMGTPEZY")
969 : QLatin1String("KMGTPEZY")).at(exp-1) + (si ? QLatin1String("")
970 : QLatin1String("i"));
971 ret = QString().asprintf("%.1f %s", bytes / qPow(unit, exp), pre.toUtf8().constData());
972 }
973
974 return (QString::fromUtf8("%1%2").arg(ret).arg(byteStr));
975 }
976
977 } // namespace Digikam
978