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 
11 static QSet<QString> kBasicInfoSet {
12  // Exif tags
17  "Exif.Image.Make",
18  "Exif.Image.Model",
19  "Exif.Photo.ExposureTime",
20  "Exif.Photo.ShutterSpeedValue",
21  "Exif.Photo.FNumber",
22  "Exif.Photo.ApertureValue",
23  "Exif.Photo.ExposureBiasValue",
24  "Exif.Photo.Flash",
25  "Exif.Photo.FocalLength",
26  "Exif.Photo.FocalLengthIn35mmFilm",
27  "ISO speed",
28  "Exif.Photo.MeteringMode",
29  "Exif.Photo.PixelXDimension",
30  "Exif.Photo.PixelYDimension",
31  // Video tags
32  "FFmpeg.format.format_long_name",
33  "FFmpeg.format.duration",
34  "FFmpeg.format.creation_time",
35  "FFmpeg.format.model",
36  "FFmpeg.format.make",
37  // Only detects tags within the first 2 streams for efficiency
38  "FFmpeg.stream0:.codec_long_name",
39  "FFmpeg.stream1:.codec_long_name",
40  "FFmpeg.stream0:.width",
41  "FFmpeg.stream1:.width",
42  "FFmpeg.stream0:.height",
43  "FFmpeg.stream1:.height",
44  "FFmpeg.stream0:.sample_rate",
45  "FFmpeg.stream1:.sample_rate",
46  "FFmpeg.stream0:.rotate",
47  "FFmpeg.stream1:.rotate" };
48 
51  : m_screen(screen), m_mgr(ImageManagerFe::getInstance())
52 {
53  m_timer.setSingleShot(true);
54  m_timer.setInterval(1s);
55  connect(&m_timer, &QTimer::timeout, this, &InfoList::Clear);
56 }
57 
58 
64 bool InfoList::Create(bool focusable)
65 {
66  bool err = false;
67  UIUtilE::Assign(&m_screen, m_btnList, "infolist", &err);
68  if (err)
69  return false;
70 
71  m_btnList->SetVisible(false);
72  m_btnList->SetCanTakeFocus(focusable);
73  return true;
74 }
75 
76 
82 void InfoList::Toggle(const ImagePtrK& im)
83 {
84  if (!im)
85  return;
86 
87  // Only focusable lists have an extra 'full' state as they can
88  // be scrolled to view it all
89  if (m_btnList->CanTakeFocus())
90  {
91  // Start showing basic info then toggle between basic/full
93 
94  // Toggle between off/basic
95  }
96  else if (m_infoVisible == kBasicInfo)
97  {
99  m_btnList->SetVisible(false);
100  return;
101  }
102  else
104 
105  Clear();
106  Update(im);
107 
108  m_btnList->SetVisible(true);
109 }
110 
111 
117 {
118  // Only handle event if info currently displayed
119  bool handled = (m_infoVisible != kNoInfo);
121 
122  m_btnList->SetVisible(false);
123 
124  return handled;
125 }
126 
127 
133 void InfoList::CreateButton(const QString& name, const QString& value)
134 {
135  if (value.isEmpty())
136  return;
137 
138  auto *item = new MythUIButtonListItem(m_btnList, "");
139 
140  InfoMap infoMap;
141  infoMap.insert("name", name);
142  infoMap.insert("value", value);
143 
144  item->SetTextFromMap(infoMap);
145 }
146 
147 
153 {
154  int dirCount = 0;
155  int imageCount = 0;
156  int videoCount = 0;
157  int size = 0;
158  m_mgr.GetDescendantCount(im.m_id, dirCount, imageCount, videoCount, size);
159 
160  QStringList report;
161  if (imageCount > 0)
162  report << tr("%Ln image(s)", "", imageCount);
163  if (videoCount > 0)
164  report << tr("%Ln video(s)", "", videoCount);
165  if (dirCount > 0)
166  report << tr("%Ln directory(ies)", "", dirCount);
167 
168  CreateButton(tr("Contains"), report.join(", "));
169  CreateButton(tr("Dir size"), ImageAdapterBase::FormatSize(size));
170 
171  if (im.IsDevice() && im.IsLocal())
172  {
173  // Returns KiB
174  int64_t total = 0;
175  int64_t used = 0;
176  int64_t free = getDiskSpace(im.m_filePath, total, used);
177  if (total > 0)
178  {
179  CreateButton(tr("Free space"), tr("%L1 (%L2\%) Used: %L3 / %L4")
180  .arg(ImageAdapterBase::FormatSize(free))
181  .arg(100 * free / total)
182  .arg(ImageAdapterBase::FormatSize(used),
184  }
185  }
186 }
187 
188 
194 {
195  if (!im || m_infoVisible == kNoInfo)
196  return;
197 
198  if (im->m_id == GALLERY_DB_ID)
199  {
200  // No metadata for root
201  Clear();
202  CreateButton(tr("Name"), m_mgr.DeviceCaption(*im));
203  CreateCount(*im);
204  return;
205  }
206 
207  // Request metadata
208  m_mgr.RequestMetaData(im->m_id);
209  // Reduce flicker by waiting for new data before clearing list
210  m_timer.start();
211 }
212 
213 
219 void InfoList::Display(ImageItemK &im, const QStringList &tagStrings)
220 {
221  // Cancel timer & build list
222  m_timer.stop();
223  Clear();
224 
225  // Each tag has 3 elements: key, label, value
226  ImageMetaData::TagMap tags = ImageMetaData::ToMap(tagStrings);
227 
228  QString tagHost = tags.take(EXIF_MYTH_HOST).value(2);
229  QString tagPath = tags.take(EXIF_MYTH_PATH).value(2);
230  QString tagName = tags.take(EXIF_MYTH_NAME).value(2);
231 
232  // Override SG
233  if (im.m_id == PHOTO_DB_ID)
234  {
235  tagPath = tr("Storage Group");
236  tagName = m_mgr.DeviceCaption(im);
237  }
238 
239  CreateButton(tr("Name"), tagName);
240 
241  // Only show non-local hostnames
242  QString host = (tagHost == gCoreContext->GetHostName()) ? "" : tagHost + ":";
243  QString clone = (im.m_type == kCloneDir) ? tr("(and others)") : "";
244  CreateButton(tr("Path"), QString("%1%2 %3").arg(host, tagPath, clone));
245 
246  if (im.IsDevice())
247  {
248  CreateButton(tr("Last scan"),
251  }
252 
253  if (im.IsDirectory())
254  CreateCount(im);
255 
256  if (!im.IsDevice())
257  {
258  CreateButton(tr("Modified"),
261  }
262 
263  if (im.IsFile())
264  {
265  CreateButton(tr("File size"), tags.take(EXIF_MYTH_SIZE).value(2));
266  CreateButton(tr("Orientation"), tags.take(EXIF_MYTH_ORIENT).value(2));
267 
268  // Create buttons for exif/video tags
269  // Multimap iterates each key latest->earliest so we must do it the long way
270  QList groups = tags.uniqueKeys();
271  for (const QString & group : qAsConst(groups))
272  {
273  // Iterate earliest->latest to preserve tag order
274  using TagList = QList<QStringList>;
275  TagList tagList = tags.values(group);
276  TagList::const_iterator i = tagList.constEnd();
277 
278  if (m_infoVisible == kFullInfo)
279  {
280  // Show all tags
281  while (i-- != tagList.constBegin())
282  CreateButton(i->at(1), i->at(2));
283  }
284  else
285  {
286  // Only show specific keys
287  while (i-- != tagList.constBegin())
288  if (kBasicInfoSet.contains(i->at(0)))
289  CreateButton(i->at(1), i->at(2));
290  }
291  }
292 
293  // Only give list focus if requested
294  if (m_btnList->CanTakeFocus())
296  }
297 }
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:219
PHOTO_DB_ID
#define PHOTO_DB_ID
Definition: imagetypes.h:29
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:97
InfoList::CreateButton
void CreateButton(const QString &name, const QString &value)
Populate a buttonlist item with exif tag name & value.
Definition: galleryinfo.cpp:133
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:43
ImageItem::IsLocal
bool IsLocal() const
Definition: imagetypes.h:119
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
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:193
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:44
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:2392
MythUIButtonListItem
Definition: mythuibuttonlist.h:27
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
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:82
MythScreenType::SetFocusWidget
bool SetFocusWidget(MythUIType *widget=nullptr)
Definition: mythscreentype.cpp:117
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
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:152
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:11
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:1934
InfoList::Hide
bool Hide()
Remove infolist from display.
Definition: galleryinfo.cpp:116
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:456
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:117
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:862
ImageItem::IsDevice
bool IsDevice() const
Definition: imagetypes.h:116
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:64
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:23
ImageManagerFe::RequestMetaData
void RequestMetaData(int id)
Requests all exif/ffmpeg tags for an image, which returns by event.
Definition: imagemanager.cpp:2168
InfoList::InfoList
InfoList(MythScreenType &screen)
Constructor.
Definition: galleryinfo.cpp:50
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:37
GALLERY_DB_ID
#define GALLERY_DB_ID
Definition: imagetypes.h:27
ImageItem::m_filePath
QString m_filePath
Absolute for local images. Usually SG-relative for remotes.
Definition: imagetypes.h:93