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  }
98  else if (m_infoVisible == kBasicInfo)
99  {
101  m_btnList->SetVisible(false);
102  return;
103  }
104  else
106 
107  Clear();
108  Update(im);
109 
110  m_btnList->SetVisible(true);
111 }
112 
113 
119 {
120  // Only handle event if info currently displayed
121  bool handled = (m_infoVisible != kNoInfo);
123 
124  m_btnList->SetVisible(false);
125 
126  return handled;
127 }
128 
129 
135 void InfoList::CreateButton(const QString& name, const QString& value)
136 {
137  if (value.isEmpty())
138  return;
139 
140  auto *item = new MythUIButtonListItem(m_btnList, "");
141 
142  InfoMap infoMap;
143  infoMap.insert("name", name);
144  infoMap.insert("value", value);
145 
146  item->SetTextFromMap(infoMap);
147 }
148 
149 
155 {
156  int dirCount = 0;
157  int imageCount = 0;
158  int videoCount = 0;
159  int size = 0;
160  m_mgr.GetDescendantCount(im.m_id, dirCount, imageCount, videoCount, size);
161 
162  QStringList report;
163  if (imageCount > 0)
164  report << tr("%Ln image(s)", "", imageCount);
165  if (videoCount > 0)
166  report << tr("%Ln video(s)", "", videoCount);
167  if (dirCount > 0)
168  report << tr("%Ln directory(ies)", "", dirCount);
169 
170  CreateButton(tr("Contains"), report.join(", "));
171  CreateButton(tr("Dir size"), ImageAdapterBase::FormatSize(size));
172 
173  if (im.IsDevice() && im.IsLocal())
174  {
175  // Returns KiB
176  int64_t total = 0;
177  int64_t used = 0;
178  int64_t free = getDiskSpace(im.m_filePath, total, used);
179  if (total > 0)
180  {
181  CreateButton(tr("Free space"), tr("%L1 (%L2\%) Used: %L3 / %L4")
182  .arg(ImageAdapterBase::FormatSize(free))
183  .arg(100 * free / total)
184  .arg(ImageAdapterBase::FormatSize(used),
186  }
187  }
188 }
189 
190 
196 {
197  if (!im || m_infoVisible == kNoInfo)
198  return;
199 
200  if (im->m_id == GALLERY_DB_ID)
201  {
202  // No metadata for root
203  Clear();
204  CreateButton(tr("Name"), m_mgr.DeviceCaption(*im));
205  CreateCount(*im);
206  return;
207  }
208 
209  // Request metadata
210  m_mgr.RequestMetaData(im->m_id);
211  // Reduce flicker by waiting for new data before clearing list
212  m_timer.start();
213 }
214 
215 
221 void InfoList::Display(ImageItemK &im, const QStringList &tagStrings)
222 {
223  // Cancel timer & build list
224  m_timer.stop();
225  Clear();
226 
227  // Each tag has 3 elements: key, label, value
228  ImageMetaData::TagMap tags = ImageMetaData::ToMap(tagStrings);
229 
230  QString tagHost = tags.take(EXIF_MYTH_HOST).value(2);
231  QString tagPath = tags.take(EXIF_MYTH_PATH).value(2);
232  QString tagName = tags.take(EXIF_MYTH_NAME).value(2);
233 
234  // Override SG
235  if (im.m_id == PHOTO_DB_ID)
236  {
237  tagPath = tr("Storage Group");
238  tagName = m_mgr.DeviceCaption(im);
239  }
240 
241  CreateButton(tr("Name"), tagName);
242 
243  // Only show non-local hostnames
244  QString host = (tagHost == gCoreContext->GetHostName()) ? "" : tagHost + ":";
245  QString clone = (im.m_type == kCloneDir) ? tr("(and others)") : "";
246  CreateButton(tr("Path"), QString("%1%2 %3").arg(host, tagPath, clone));
247 
248  if (im.IsDevice())
249  {
250 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
251  CreateButton(tr("Last scan"),
252  MythDate::toString(QDateTime::fromTime_t(im.m_date),
254 #else
255  CreateButton(tr("Last scan"),
258 #endif
259  }
260 
261  if (im.IsDirectory())
262  CreateCount(im);
263 
264  if (!im.IsDevice())
265  {
266 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
267  CreateButton(tr("Modified"),
268  MythDate::toString(QDateTime::fromTime_t(im.m_modTime),
270 #else
271  CreateButton(tr("Modified"),
274 #endif
275  }
276 
277  if (im.IsFile())
278  {
279  CreateButton(tr("File size"), tags.take(EXIF_MYTH_SIZE).value(2));
280  CreateButton(tr("Orientation"), tags.take(EXIF_MYTH_ORIENT).value(2));
281 
282  // Create buttons for exif/video tags
283  // Multimap iterates each key latest->earliest so we must do it the long way
284  foreach (const QString &group, tags.uniqueKeys())
285  {
286  // Iterate earliest->latest to preserve tag order
287  using TagList = QList<QStringList>;
288  TagList tagList = tags.values(group);
289  TagList::const_iterator i = tagList.constEnd();
290 
291  if (m_infoVisible == kFullInfo)
292  {
293  // Show all tags
294  while (i-- != tagList.constBegin())
295  CreateButton(i->at(1), i->at(2));
296  }
297  else
298  {
299  // Only show specific keys
300  while (i-- != tagList.constBegin())
301  if (kBasicInfoSet.contains(i->at(0)))
302  CreateButton(i->at(1), i->at(2));
303  }
304  }
305 
306  // Only give list focus if requested
307  if (m_btnList->CanTakeFocus())
309  }
310 }
static QString FormatSize(int sizeKib)
Definition: imagemanager.h:143
#define EXIF_TAG_DATETIME
Definition: imagemetadata.h:26
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:456
qint64 m_date
Image creation date, from Exif metadata.
Definition: imagetypes.h:106
QString m_filePath
Absolute for local images. Usually SG-relative for remotes.
Definition: imagetypes.h:92
#define EXIF_MYTH_SIZE
Definition: imagemetadata.h:41
void CreateButton(const QString &name, const QString &value)
Populate a buttonlist item with exif tag name & value.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool IsDevice() const
Definition: imagetypes.h:123
bool IsLocal() const
Definition: imagetypes.h:126
MythScreenType & m_screen
Parent screen.
Definition: galleryinfo.h:42
Handles Exif/FFMpeg metadata tags for images.
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:172
#define EXIF_TAG_ORIENTATION
Definition: imagemetadata.h:25
InfoVisibleState m_infoVisible
Info list state.
Definition: galleryinfo.h:44
Default local time.
Definition: mythdate.h:20
#define EXIF_TAG_USERCOMMENT
Definition: imagemetadata.h:29
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:42
void Update(const ImagePtrK &im)
Populates available exif details for the current image/dir.
QTimer m_timer
Clears list if no new metadata arrives.
Definition: galleryinfo.h:46
The info/details overlay that shows image metadata.
#define EXIF_TAG_IMAGEDESCRIPTION
Definition: imagemetadata.h:28
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:100
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
void CreateCount(ImageItemK &im)
Creates buttons detailing dir counts & size.
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
#define EXIF_MYTH_PATH
Definition: imagemetadata.h:39
static QStringList kBasicInfoFields
Definition: galleryinfo.cpp:9
bool IsDirectory() const
Definition: imagetypes.h:124
int64_t getDiskSpace(const QString &file_on_disk, int64_t &total, int64_t &used)
Shows all exif tags.
Definition: galleryinfo.h:18
void Toggle(const ImagePtrK &im)
Toggle infolist state for an image. Focusable widgets toggle between Basic & Full info....
Definition: galleryinfo.cpp:84
QString DeviceCaption(ImageItemK &im) const
Return translated device name.
void Clear()
Definition: galleryinfo.h:36
bool IsFile() const
Definition: imagetypes.h:125
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:334
ImageManagerFe & m_mgr
Image Manager.
Definition: galleryinfo.h:45
#define EXIF_MYTH_HOST
Definition: imagemetadata.h:38
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:96
#define EXIF_MYTH_NAME
Definition: imagemetadata.h:40
#define PHOTO_DB_ID
Definition: imagetypes.h:28
bool SetFocusWidget(MythUIType *widget=nullptr)
Screen in which all other widgets are contained and rendered.
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:88
QString GetHostName(void)
QMap< QString, QStringList > TagMap
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:342
#define GALLERY_DB_ID
Definition: imagetypes.h:26
A device sub dir comprised from multiple SG dirs.
Definition: imagetypes.h:36