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