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
107 
108  Clear();
109  Update(im);
110 
111  m_btnList->SetVisible(true);
112 }
113 
114 
120 {
121  // Only handle event if info currently displayed
122  bool handled = (m_infoVisible != kNoInfo);
124 
125  m_btnList->SetVisible(false);
126 
127  return handled;
128 }
129 
130 
136 void InfoList::CreateButton(const QString& name, const QString& value)
137 {
138  if (value.isEmpty())
139  return;
140 
141  auto *item = new MythUIButtonListItem(m_btnList, "");
142 
143  InfoMap infoMap;
144  infoMap.insert("name", name);
145  infoMap.insert("value", value);
146 
147  item->SetTextFromMap(infoMap);
148 }
149 
150 
156 {
157  int dirCount = 0;
158  int imageCount = 0;
159  int videoCount = 0;
160  int size = 0;
161  m_mgr.GetDescendantCount(im.m_id, dirCount, imageCount, videoCount, size);
162 
163  QStringList report;
164  if (imageCount > 0)
165  report << tr("%Ln image(s)", "", imageCount);
166  if (videoCount > 0)
167  report << tr("%Ln video(s)", "", videoCount);
168  if (dirCount > 0)
169  report << tr("%Ln directory(ies)", "", dirCount);
170 
171  CreateButton(tr("Contains"), report.join(", "));
172  CreateButton(tr("Dir size"), ImageAdapterBase::FormatSize(size));
173 
174  if (im.IsDevice() && im.IsLocal())
175  {
176  // Returns KiB
177  int64_t total = 0;
178  int64_t used = 0;
179  int64_t free = getDiskSpace(im.m_filePath, total, used);
180  if (total > 0)
181  {
182  CreateButton(tr("Free space"), tr("%L1 (%L2\%) Used: %L3 / %L4")
183  .arg(ImageAdapterBase::FormatSize(free))
184  .arg(100 * free / total)
185  .arg(ImageAdapterBase::FormatSize(used),
187  }
188  }
189 }
190 
191 
197 {
198  if (!im || m_infoVisible == kNoInfo)
199  return;
200 
201  if (im->m_id == GALLERY_DB_ID)
202  {
203  // No metadata for root
204  Clear();
205  CreateButton(tr("Name"), m_mgr.DeviceCaption(*im));
206  CreateCount(*im);
207  return;
208  }
209 
210  // Request metadata
211  m_mgr.RequestMetaData(im->m_id);
212  // Reduce flicker by waiting for new data before clearing list
213  m_timer.start();
214 }
215 
216 
222 void InfoList::Display(ImageItemK &im, const QStringList &tagStrings)
223 {
224  // Cancel timer & build list
225  m_timer.stop();
226  Clear();
227 
228  // Each tag has 3 elements: key, label, value
229  ImageMetaData::TagMap tags = ImageMetaData::ToMap(tagStrings);
230 
231  QString tagHost = tags.take(EXIF_MYTH_HOST).value(2);
232  QString tagPath = tags.take(EXIF_MYTH_PATH).value(2);
233  QString tagName = tags.take(EXIF_MYTH_NAME).value(2);
234 
235  // Override SG
236  if (im.m_id == PHOTO_DB_ID)
237  {
238  tagPath = tr("Storage Group");
239  tagName = m_mgr.DeviceCaption(im);
240  }
241 
242  CreateButton(tr("Name"), tagName);
243 
244  // Only show non-local hostnames
245  QString host = (tagHost == gCoreContext->GetHostName()) ? "" : tagHost + ":";
246  QString clone = (im.m_type == kCloneDir) ? tr("(and others)") : "";
247  CreateButton(tr("Path"), QString("%1%2 %3").arg(host, tagPath, clone));
248 
249  if (im.IsDevice())
250  {
251  CreateButton(tr("Last scan"),
254  }
255 
256  if (im.IsDirectory())
257  CreateCount(im);
258 
259  if (!im.IsDevice())
260  {
261  CreateButton(tr("Modified"),
264  }
265 
266  if (im.IsFile())
267  {
268  CreateButton(tr("File size"), tags.take(EXIF_MYTH_SIZE).value(2));
269  CreateButton(tr("Orientation"), tags.take(EXIF_MYTH_ORIENT).value(2));
270 
271  // Create buttons for exif/video tags
272  // Multimap iterates each key latest->earliest so we must do it the long way
273  QList groups = tags.uniqueKeys();
274  for (const QString & group : qAsConst(groups))
275  {
276  // Iterate earliest->latest to preserve tag order
277  using TagList = QList<QStringList>;
278  TagList tagList = tags.values(group);
279  TagList::const_iterator i = tagList.constEnd();
280 
281  if (m_infoVisible == kFullInfo)
282  {
283  // Show all tags
284  while (i-- != tagList.constBegin())
285  CreateButton(i->at(1), i->at(2));
286  }
287  else
288  {
289  // Only show specific keys
290  while (i-- != tagList.constBegin())
291  if (kBasicInfoSet.contains(i->at(0)))
292  CreateButton(i->at(1), i->at(2));
293  }
294  }
295 
296  // Only give list focus if requested
297  if (m_btnList->CanTakeFocus())
299  }
300 }
ImagePtrK
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:165
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:222
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:103
MythUIType::CanTakeFocus
bool CanTakeFocus(void) const
Return if this widget can accept input focus.
Definition: mythuitype.cpp:349
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:97
InfoList::CreateButton
void CreateButton(const QString &name, const QString &value)
Populate a buttonlist item with exif tag name & value.
Definition: galleryinfo.cpp:136
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:44
mythcoreutil.h
MythUIType::SetCanTakeFocus
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:357
kNoInfo
@ kNoInfo
Details not displayed.
Definition: galleryinfo.h:16
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:196
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:46
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
ImageManagerFe::DeviceCaption
QString DeviceCaption(ImageItemK &im) const
Return translated device name.
Definition: imagemanager.cpp:2385
MythUIButtonListItem
Definition: mythuibuttonlist.h:41
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:118
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
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:719
InfoList::Clear
void Clear()
Definition: galleryinfo.h:36
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:155
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:1927
InfoList::Hide
bool Hide()
Remove infolist from display.
Definition: galleryinfo.cpp:119
kFullInfo
@ kFullInfo
Shows all exif tags.
Definition: galleryinfo.h:18
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:459
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.
kBasicInfo
@ kBasicInfo
Shows just the most useful exif tags.
Definition: galleryinfo.h:17
EXIF_MYTH_HOST
static constexpr const char * EXIF_MYTH_HOST
Definition: imagemetadata.h:38
MythUIType::SetVisible
virtual void SetVisible(bool visible)
Definition: mythuitype.cpp:1108
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:837
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:2161
InfoList::InfoList
InfoList(MythScreenType &screen)
Constructor.
Definition: galleryinfo.cpp:53
kCloneDir
@ kCloneDir
A device sub dir comprised from multiple SG dirs.
Definition: imagetypes.h:37
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