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