MythTV  master
galleryinfo.cpp
Go to the documentation of this file.
1 #include "galleryinfo.h"
2 
3 #include "mythcoreutil.h"
4 #include "mythdate.h"
5 #include "imagemetadata.h"
6 
7 
8 // Only Used to initialise the QSet of keys
9 static QStringList kBasicInfoFields = QStringList()
10  // Exif tags
15  << "Exif.Image.Make"
16  << "Exif.Image.Model"
17  << "Exif.Photo.ExposureTime"
18  << "Exif.Photo.ShutterSpeedValue"
19  << "Exif.Photo.FNumber"
20  << "Exif.Photo.ApertureValue"
21  << "Exif.Photo.ExposureBiasValue"
22  << "Exif.Photo.Flash"
23  << "Exif.Photo.FocalLength"
24  << "Exif.Photo.FocalLengthIn35mmFilm"
25  << "ISO speed"
26  << "Exif.Photo.MeteringMode"
27  << "Exif.Photo.PixelXDimension"
28  << "Exif.Photo.PixelYDimension"
29  // Video tags
30  << "FFmpeg.format.format_long_name"
31  << "FFmpeg.format.duration"
32  << "FFmpeg.format.creation_time"
33  << "FFmpeg.format.model"
34  << "FFmpeg.format.make"
35  // Only detects tags within the first 2 streams for efficiency
36  << "FFmpeg.stream0:.codec_long_name"
37  << "FFmpeg.stream1:.codec_long_name"
38  << "FFmpeg.stream0:.width"
39  << "FFmpeg.stream1:.width"
40  << "FFmpeg.stream0:.height"
41  << "FFmpeg.stream1:.height"
42  << "FFmpeg.stream0:.sample_rate"
43  << "FFmpeg.stream1:.sample_rate"
44  << "FFmpeg.stream0:.rotate"
45  << "FFmpeg.stream1:.rotate";
46 
48 static QSet<QString> kBasicInfoSet = QSet<QString>::fromList(kBasicInfoFields);
49 
50 
53  : m_screen(screen), m_mgr(ImageManagerFe::getInstance())
54 {
55  m_timer.setSingleShot(true);
56  m_timer.setInterval(1000);
57  connect(&m_timer, SIGNAL(timeout()), this, SLOT(Clear()));
58 }
59 
60 
66 bool InfoList::Create(bool focusable)
67 {
68  bool err = false;
69  UIUtilE::Assign(&m_screen, m_btnList, "infolist", &err);
70  if (err)
71  return false;
72 
73  m_btnList->SetVisible(false);
74  m_btnList->SetCanTakeFocus(focusable);
75  return true;
76 }
77 
78 
84 void InfoList::Toggle(const ImagePtrK& im)
85 {
86  if (!im)
87  return;
88 
89  // Only focusable lists have an extra 'full' state as they can
90  // be scrolled to view it all
91  if (m_btnList->CanTakeFocus())
92 
93  // Start showing basic info then toggle between basic/full
95 
96  // Toggle between off/basic
97  else if (m_infoVisible == kBasicInfo)
98  {
100  m_btnList->SetVisible(false);
101  return;
102  }
103  else
105 
106  Clear();
107  Update(im);
108 
109  m_btnList->SetVisible(true);
110 }
111 
112 
118 {
119  // Only handle event if info currently displayed
120  bool handled = (m_infoVisible != kNoInfo);
122 
123  m_btnList->SetVisible(false);
124 
125  return handled;
126 }
127 
128 
134 void InfoList::CreateButton(const QString& name, const QString& value)
135 {
136  if (value.isEmpty())
137  return;
138 
139  auto *item = new MythUIButtonListItem(m_btnList, "");
140 
141  InfoMap infoMap;
142  infoMap.insert("name", name);
143  infoMap.insert("value", value);
144 
145  item->SetTextFromMap(infoMap);
146 }
147 
148 
154 {
155  int dirCount = 0, imageCount = 0, videoCount = 0, size = 0;
156  m_mgr.GetDescendantCount(im.m_id, dirCount, imageCount, videoCount, size);
157 
158  QStringList report;
159  if (imageCount > 0)
160  report << tr("%Ln image(s)", "", imageCount);
161  if (videoCount > 0)
162  report << tr("%Ln video(s)", "", videoCount);
163  if (dirCount > 0)
164  report << tr("%Ln directory(ies)", "", dirCount);
165 
166  CreateButton(tr("Contains"), report.join(", "));
167  CreateButton(tr("Dir size"), ImageAdapterBase::FormatSize(size));
168 
169  if (im.IsDevice() && im.IsLocal())
170  {
171  // Returns KiB
172  int64_t total = 0, used = 0;
173  int64_t free = getDiskSpace(im.m_filePath, total, used);
174  if (total > 0)
175  CreateButton(tr("Free space"), tr("%L1 (%L2\%) Used: %L3 / %L4")
176  .arg(ImageAdapterBase::FormatSize(free))
177  .arg(100 * free / total)
178  .arg(ImageAdapterBase::FormatSize(used),
180  }
181 }
182 
183 
189 {
190  if (!im || m_infoVisible == kNoInfo)
191  return;
192 
193  if (im->m_id == GALLERY_DB_ID)
194  {
195  // No metadata for root
196  Clear();
197  CreateButton(tr("Name"), m_mgr.DeviceCaption(*im));
198  CreateCount(*im);
199  return;
200  }
201 
202  // Request metadata
203  m_mgr.RequestMetaData(im->m_id);
204  // Reduce flicker by waiting for new data before clearing list
205  m_timer.start();
206 }
207 
208 
214 void InfoList::Display(ImageItemK &im, const QStringList &tagStrings)
215 {
216  // Cancel timer & build list
217  m_timer.stop();
218  Clear();
219 
220  // Each tag has 3 elements: key, label, value
221  ImageMetaData::TagMap tags = ImageMetaData::ToMap(tagStrings);
222 
223  QString tagHost = tags.take(EXIF_MYTH_HOST).value(2);
224  QString tagPath = tags.take(EXIF_MYTH_PATH).value(2);
225  QString tagName = tags.take(EXIF_MYTH_NAME).value(2);
226 
227  // Override SG
228  if (im.m_id == PHOTO_DB_ID)
229  {
230  tagPath = tr("Storage Group");
231  tagName = m_mgr.DeviceCaption(im);
232  }
233 
234  CreateButton(tr("Name"), tagName);
235 
236  // Only show non-local hostnames
237  QString host = (tagHost == gCoreContext->GetHostName()) ? "" : tagHost + ":";
238  QString clone = (im.m_type == kCloneDir) ? tr("(and others)") : "";
239  CreateButton(tr("Path"), QString("%1%2 %3").arg(host, tagPath, clone));
240 
241  if (im.IsDevice())
242  CreateButton(tr("Last scan"),
243 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
244  MythDate::toString(QDateTime::fromTime_t(im.m_date),
245 #else
247 #endif
249 
250  if (im.IsDirectory())
251  CreateCount(im);
252 
253  if (!im.IsDevice())
254  CreateButton(tr("Modified"),
255 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
256  MythDate::toString(QDateTime::fromTime_t(im.m_modTime),
257 #else
259 #endif
261 
262  if (im.IsFile())
263  {
264  CreateButton(tr("File size"), tags.take(EXIF_MYTH_SIZE).value(2));
265  CreateButton(tr("Orientation"), tags.take(EXIF_MYTH_ORIENT).value(2));
266 
267  // Create buttons for exif/video tags
268  // Multimap iterates each key latest->earliest so we must do it the long way
269  foreach (const QString &group, tags.uniqueKeys())
270  {
271  // Iterate earliest->latest to preserve tag order
272  using TagList = QList<QStringList>;
273  TagList tagList = tags.values(group);
274  TagList::const_iterator i = tagList.constEnd();
275 
276  if (m_infoVisible == kFullInfo)
277  {
278  // Show all tags
279  while (i-- != tagList.constBegin())
280  CreateButton(i->at(1), i->at(2));
281  }
282  else
283  {
284  // Only show specific keys
285  while (i-- != tagList.constBegin())
286  if (kBasicInfoSet.contains(i->at(0)))
287  CreateButton(i->at(1), i->at(2));
288  }
289  }
290 
291  // Only give list focus if requested
292  if (m_btnList->CanTakeFocus())
294  }
295 }
static QString FormatSize(int sizeKib)
Definition: imagemanager.h:139
#define EXIF_TAG_DATETIME
Definition: imagemetadata.h:22
Shows just the most useful exif tags.
Definition: galleryinfo.h:17
bool Create(bool focusable)
Initialise buttonlist from XML.
Definition: galleryinfo.cpp:66
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
void GetDescendantCount(int id, int &dirs, int &pics, int &videos, int &sizeKb) const
Return counts of dirs, pics and videos in the subtree of a dir. Also dir size.
The image manager for use by Frontends.
Definition: imagemanager.h:452
qint64 m_date
Image creation date, from Exif metadata.
Definition: imagetypes.h:114
QString m_filePath
Absolute for local images. Usually SG-relative for remotes.
Definition: imagetypes.h:100
#define EXIF_MYTH_SIZE
Definition: imagemetadata.h:37
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool IsDevice() const
Definition: imagetypes.h:131
bool IsLocal() const
Definition: imagetypes.h:134
MythScreenType & m_screen
Parent screen.
Definition: galleryinfo.h:42
Handles Exif/FFMpeg metadata tags for images.
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:179
#define EXIF_TAG_ORIENTATION
Definition: imagemetadata.h:21
InfoVisibleState m_infoVisible
Info list state.
Definition: galleryinfo.h:44
Default local time.
Definition: mythdate.h:20
#define EXIF_TAG_USERCOMMENT
Definition: imagemetadata.h:25
virtual void SetVisible(bool visible)
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(uint seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
Definition: mythdate.cpp:88
#define EXIF_MYTH_ORIENT
Definition: imagemetadata.h:38
QTimer m_timer
Clears list if no new metadata arrives.
Definition: galleryinfo.h:46
void CreateCount(ImageItemK &)
Creates buttons detailing dir counts & size.
The info/details overlay that shows image metadata.
#define EXIF_TAG_IMAGEDESCRIPTION
Definition: imagemetadata.h:24
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
qint64 m_modTime
Filesystem modified datestamp.
Definition: imagetypes.h:108
Add year to string if not included.
Definition: mythdate.h:22
static QSet< QString > kBasicInfoSet
The exif/video tags comprising the Basic file info.
Definition: galleryinfo.cpp:48
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:101
Details not displayed.
Definition: galleryinfo.h:16
void Update(const ImagePtrK &)
Populates available exif details for the current image/dir.
#define EXIF_MYTH_PATH
Definition: imagemetadata.h:35
static QStringList kBasicInfoFields
Definition: galleryinfo.cpp:9
bool IsDirectory() const
Definition: imagetypes.h:132
int64_t getDiskSpace(const QString &file_on_disk, int64_t &total, int64_t &used)
Shows all exif tags.
Definition: galleryinfo.h:18
QString DeviceCaption(ImageItemK &im) const
Return translated device name.
void Clear()
Definition: galleryinfo.h:36
bool IsFile() const
Definition: imagetypes.h:133
static TagMap ToMap(const QStringList &tags)
Creates a map of metadata tags as.
bool CanTakeFocus(void) const
Return if this widget can accept input focus.
Definition: mythuitype.cpp:336
void Toggle(const ImagePtrK &)
Toggle infolist state for an image. Focusable widgets toggle between Basic & Full info....
Definition: galleryinfo.cpp:84
ImageManagerFe & m_mgr
Image Manager.
Definition: galleryinfo.h:45
#define EXIF_MYTH_HOST
Definition: imagemetadata.h:34
InfoList(MythScreenType &screen)
Constructor.
Definition: galleryinfo.cpp:52
Represents a picture, video or directory.
Definition: imagetypes.h:67
bool Hide()
Remove infolist from display.
int m_type
Type of node: dir, video etc.
Definition: imagetypes.h:104
#define EXIF_MYTH_NAME
Definition: imagemetadata.h:36
#define PHOTO_DB_ID
Definition: imagetypes.h:28
bool SetFocusWidget(MythUIType *widget=nullptr)
Screen in which all other widgets are contained and rendered.
void CreateButton(const QString &, const QString &)
Populate a buttonlist item with exif tag name & value.
MythUIButtonList * m_btnList
Overlay buttonlist.
Definition: galleryinfo.h:43
void Display(ImageItemK &im, const QStringList &tagStrings)
Build list of metadata tags.
void RequestMetaData(int id)
Requests all exif/ffmpeg tags for an image, which returns by event.
int m_id
Uniquely identifies an image (file/dir).
Definition: imagetypes.h:96
QString GetHostName(void)
QMap< QString, QStringList > TagMap
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:344
#define GALLERY_DB_ID
Definition: imagetypes.h:26
A device sub dir comprised from multiple SG dirs.
Definition: imagetypes.h:36