MythTV  master
galleryinfo.cpp
Go to the documentation of this file.
1 #include <chrono>
2 
3 #include "galleryinfo.h"
4 
5 #include "imagemetadata.h"
6 #include "mythcoreutil.h"
7 #include "mythdate.h"
8 
9 using namespace std::chrono_literals;
10 
11 
13 static QSet<QString> kBasicInfoSet {
14  // Exif tags
19  "Exif.Image.Make",
20  "Exif.Image.Model",
21  "Exif.Photo.ExposureTime",
22  "Exif.Photo.ShutterSpeedValue",
23  "Exif.Photo.FNumber",
24  "Exif.Photo.ApertureValue",
25  "Exif.Photo.ExposureBiasValue",
26  "Exif.Photo.Flash",
27  "Exif.Photo.FocalLength",
28  "Exif.Photo.FocalLengthIn35mmFilm",
29  "ISO speed",
30  "Exif.Photo.MeteringMode",
31  "Exif.Photo.PixelXDimension",
32  "Exif.Photo.PixelYDimension",
33  // Video tags
34  "FFmpeg.format.format_long_name",
35  "FFmpeg.format.duration",
36  "FFmpeg.format.creation_time",
37  "FFmpeg.format.model",
38  "FFmpeg.format.make",
39  // Only detects tags within the first 2 streams for efficiency
40  "FFmpeg.stream0:.codec_long_name",
41  "FFmpeg.stream1:.codec_long_name",
42  "FFmpeg.stream0:.width",
43  "FFmpeg.stream1:.width",
44  "FFmpeg.stream0:.height",
45  "FFmpeg.stream1:.height",
46  "FFmpeg.stream0:.sample_rate",
47  "FFmpeg.stream1:.sample_rate",
48  "FFmpeg.stream0:.rotate",
49  "FFmpeg.stream1:.rotate" };
50 
53  : m_screen(screen), m_mgr(ImageManagerFe::getInstance())
54 {
55  m_timer.setSingleShot(true);
56  m_timer.setInterval(1s);
57  connect(&m_timer, &QTimer::timeout, this, &InfoList::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")
183  .arg(100 * free / total)
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  CreateButton(tr("Last scan"),
253  }
254 
255  if (im.IsDirectory())
256  CreateCount(im);
257 
258  if (!im.IsDevice())
259  {
260  CreateButton(tr("Modified"),
263  }
264 
265  if (im.IsFile())
266  {
267  CreateButton(tr("File size"), tags.take(EXIF_MYTH_SIZE).value(2));
268  CreateButton(tr("Orientation"), tags.take(EXIF_MYTH_ORIENT).value(2));
269 
270  // Create buttons for exif/video tags
271  // Multimap iterates each key latest->earliest so we must do it the long way
272  QList groups = tags.uniqueKeys();
273  for (const QString & group : qAsConst(groups))
274  {
275  // Iterate earliest->latest to preserve tag order
276  using TagList = QList<QStringList>;
277  TagList tagList = tags.values(group);
278  TagList::const_iterator i = tagList.constEnd();
279 
280  if (m_infoVisible == kFullInfo)
281  {
282  // Show all tags
283  while (i-- != tagList.constBegin())
284  CreateButton(i->at(1), i->at(2));
285  }
286  else
287  {
288  // Only show specific keys
289  while (i-- != tagList.constBegin())
290  if (kBasicInfoSet.contains(i->at(0)))
291  CreateButton(i->at(1), i->at(2));
292  }
293  }
294 
295  // Only give list focus if requested
296  if (m_btnList->CanTakeFocus())
298  }
299 }
ImagePtrK
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:164
InfoList::m_mgr
ImageManagerFe & m_mgr
Image Manager.
Definition: galleryinfo.h:45
InfoList::m_btnList
MythUIButtonList * m_btnList
Overlay buttonlist.
Definition: galleryinfo.h:43
InfoList::Display
void Display(ImageItemK &im, const QStringList &tagStrings)
Build list of metadata tags.
Definition: galleryinfo.cpp:221
PHOTO_DB_ID
#define PHOTO_DB_ID
Definition: imagetypes.h:28
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:80
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
MythUIType::CanTakeFocus
bool CanTakeFocus(void) const
Return if this widget can accept input focus.
Definition: mythuitype.cpp:335
InfoList::m_screen
MythScreenType & m_screen
Parent screen.
Definition: galleryinfo.h:42
ImageItem::m_type
int m_type
Type of node: dir, video etc.
Definition: imagetypes.h:96
InfoList::CreateButton
void CreateButton(const QString &name, const QString &value)
Populate a buttonlist item with exif tag name & value.
Definition: galleryinfo.cpp:135
ImageItem::m_id
int m_id
Uniquely identifies an image (file/dir).
Definition: imagetypes.h:88
getDiskSpace
int64_t getDiskSpace(const QString &file_on_disk, int64_t &total, int64_t &used)
Definition: mythcoreutil.cpp:43
ImageItem::IsLocal
bool IsLocal() const
Definition: imagetypes.h:118
InfoList::m_infoVisible
InfoVisibleState m_infoVisible
Info list state.
Definition: galleryinfo.h:44
EXIF_MYTH_SIZE
#define EXIF_MYTH_SIZE
Definition: imagemetadata.h:41
mythcoreutil.h
arg
arg(title).arg(filename).arg(doDelete))
MythUIType::SetCanTakeFocus
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:343
kNoInfo
@ kNoInfo
Details not displayed.
Definition: galleryinfo.h:16
InfoList::Update
void Update(const ImagePtrK &im)
Populates available exif details for the current image/dir.
Definition: galleryinfo.cpp:195
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:45
EXIF_TAG_ORIENTATION
#define EXIF_TAG_ORIENTATION
Definition: imagemetadata.h:25
InfoList::m_timer
QTimer m_timer
Clears list if no new metadata arrives.
Definition: galleryinfo.h:46
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
EXIF_TAG_USERCOMMENT
#define EXIF_TAG_USERCOMMENT
Definition: imagemetadata.h:29
ImageManagerFe::DeviceCaption
QString DeviceCaption(ImageItemK &im) const
Return translated device name.
Definition: imagemanager.cpp:2387
MythUIButtonListItem
Definition: mythuibuttonlist.h:28
EXIF_MYTH_ORIENT
#define EXIF_MYTH_ORIENT
Definition: imagemetadata.h:42
MythDate::fromSecsSinceEpoch
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:68
ImageItem::m_modTime
qint64 m_modTime
Filesystem modified datestamp.
Definition: imagetypes.h:97
mythdate.h
InfoList::Toggle
void Toggle(const ImagePtrK &im)
Toggle infolist state for an image. Focusable widgets toggle between Basic & Full info....
Definition: galleryinfo.cpp:84
MythScreenType::SetFocusWidget
bool SetFocusWidget(MythUIType *widget=nullptr)
Definition: mythscreentype.cpp:117
ImageAdapterBase::FormatSize
static QString FormatSize(int sizeKib)
Definition: imagemanager.h:143
EXIF_TAG_IMAGEDESCRIPTION
#define EXIF_TAG_IMAGEDESCRIPTION
Definition: imagemetadata.h:28
ImageMetaData::ToMap
static TagMap ToMap(const QStringList &tags)
Creates a map of metadata tags as.
Definition: imagemetadata.cpp:721
InfoList::Clear
void Clear()
Definition: galleryinfo.h:36
galleryinfo.h
The info/details overlay that shows image metadata.
EXIF_MYTH_PATH
#define EXIF_MYTH_PATH
Definition: imagemetadata.h:39
InfoList::CreateCount
void CreateCount(ImageItemK &im)
Creates buttons detailing dir counts & size.
Definition: galleryinfo.cpp:154
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
kBasicInfoSet
static QSet< QString > kBasicInfoSet
The exif/video tags comprising the Basic file info.
Definition: galleryinfo.cpp:13
ImageMetaData::TagMap
QMultiMap< QString, QStringList > TagMap
Definition: imagemetadata.h:119
ImageDbReader::GetDescendantCount
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.
Definition: imagemanager.cpp:1929
InfoList::Hide
bool Hide()
Remove infolist from display.
Definition: galleryinfo.cpp:118
kFullInfo
@ kFullInfo
Shows all exif tags.
Definition: galleryinfo.h:18
ImageItem::IsFile
bool IsFile() const
Definition: imagetypes.h:117
MythDate::kAddYear
@ kAddYear
Add year to string if not included.
Definition: mythdate.h:22
ImageManagerFe
The image manager for use by Frontends.
Definition: imagemanager.h:457
ImageItem
Represents a picture, video or directory.
Definition: imagetypes.h:68
imagemetadata.h
Handles Exif/FFMpeg metadata tags for images.
EXIF_MYTH_NAME
#define EXIF_MYTH_NAME
Definition: imagemetadata.h:40
kBasicInfo
@ kBasicInfo
Shows just the most useful exif tags.
Definition: galleryinfo.h:17
MythUIType::SetVisible
virtual void SetVisible(bool visible)
Definition: mythuitype.cpp:1086
EXIF_MYTH_HOST
#define EXIF_MYTH_HOST
Definition: imagemetadata.h:38
ImageItem::IsDirectory
bool IsDirectory() const
Definition: imagetypes.h:116
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:859
ImageItem::IsDevice
bool IsDevice() const
Definition: imagetypes.h:115
InfoList::Create
bool Create(bool focusable)
Initialise buttonlist from XML.
Definition: galleryinfo.cpp:66
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:20
ImageItem::m_date
qint64 m_date
Image creation date, from Exif metadata.
Definition: imagetypes.h:99
ImageManagerFe::RequestMetaData
void RequestMetaData(int id)
Requests all exif/ffmpeg tags for an image, which returns by event.
Definition: imagemanager.cpp:2163
InfoList::InfoList
InfoList(MythScreenType &screen)
Constructor.
Definition: galleryinfo.cpp:52
EXIF_TAG_DATETIME
#define EXIF_TAG_DATETIME
Definition: imagemetadata.h:26
kCloneDir
@ kCloneDir
A device sub dir comprised from multiple SG dirs.
Definition: imagetypes.h:36
GALLERY_DB_ID
#define GALLERY_DB_ID
Definition: imagetypes.h:26
ImageItem::m_filePath
QString m_filePath
Absolute for local images. Usually SG-relative for remotes.
Definition: imagetypes.h:92