MythTV master
galleryviews.cpp
Go to the documentation of this file.
1#include "galleryviews.h"
2
3#include <algorithm> // std::shuffle, upper_bound
4#include <cmath> // std::pow
5#include <cstdint>
6#include <iterator> // std::distance
7#include <random>
8#include <vector>
9
12
13#define LOC QString("Galleryviews: ")
14
16const static int kMaxFolderThumbnails = 4;
17
24const double LEADING_BETA_SHAPE = 0.175;
26const double TRAILING_BETA_SHAPE = 0.31;
27
29const double DEFAULT_WEIGHT = std::pow(0.5, TRAILING_BETA_SHAPE - 1) *
30 std::pow(0.5, LEADING_BETA_SHAPE - 1);
32static constexpr qint64 BETA_CLIP { 24LL * 60 * 60 };
33
34void MarkedFiles::Add(const ImageIdList& newIds)
35{
36 for (int newid : newIds)
37 insert(newid);
38}
39
41{
42 QSet tmp;
43 for (int tmpint : all)
44 tmp.insert(tmpint);
45 for (int tmpint : std::as_const(*this))
46 tmp.remove(tmpint);
47 swap(tmp);
48}
49
55{
56 ImageListK files;
57 for (int id : std::as_const(m_sequence))
58 files.append(m_images.value(id));
59 return files;
60}
61
62
68{
69 return m_active < 0 || m_active >= m_sequence.size()
70 ? ImagePtrK() : m_images.value(m_sequence.at(m_active));
71}
72
73
78QString FlatView::GetPosition() const
79{
80 return QString("%1/%2").arg(m_active + 1).arg(m_sequence.size());
81}
82
83
89bool FlatView::Update(int id)
90{
91 ImagePtrK im = m_images.value(id);
92 if (!im)
93 return false;
94
95 // Get updated image
96 ImageList files;
97 ImageList dirs;
98 ImageIdList ids = ImageIdList() << id;
99 if (m_mgr.GetImages(ids, files, dirs) != 1 || files.size() != 1)
100 return false;
101
102 bool active = (im == GetSelected());
103
104 // Replace image
105 m_images.insert(id, files.at(0));
106
107 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Modified id %1").arg(id));
108
109 return active;
110}
111
112
120bool FlatView::Select(int id, int fallback)
121{
122 // Select first appearance of image
123 int index = m_sequence.indexOf(id);
124 if (index >= 0)
125 {
126 m_active = index;
127 return true;
128 }
129
130 if (fallback >= 0)
131 m_active = fallback;
132
133 return false;
134}
135
136
141void FlatView::Clear(bool resetParent)
142{
143 m_images.clear();
144 m_sequence.clear();
145 m_active = -1;
146 if (resetParent)
148}
149
150
156{
157 return m_sequence.isEmpty() || m_active + inc >= m_sequence.size()
158 ? ImagePtrK() : m_images.value(m_sequence.at(m_active + inc));
159}
160
161
168{
169 if (m_sequence.isEmpty())
170 return {};
171
172 // Preserve index as it may be reset when wrapping
173 int next = m_active + inc;
174
175 // Regenerate unordered views when wrapping
176 if (next >= m_sequence.size() && m_order != kOrdered && !LoadFromDb(m_parentId))
177 // Images have disappeared
178 return {};
179
180 m_active = next % m_sequence.size();
181 return m_images.value(m_sequence.at(m_active));
182}
183
184
190{
191 return m_sequence.isEmpty() || m_active < inc
192 ? ImagePtrK() : m_images.value(m_sequence.at(m_active - inc));
193}
194
195
201{
202 if (m_sequence.isEmpty())
203 return {};
204
205 // Wrap avoiding modulo of negative uncertainty
206 m_active -= inc % m_sequence.size();
207 if (m_active < 0)
208 m_active += m_sequence.size();
209
210 return m_images.value(m_sequence.at(m_active));
211}
212
213
219{
220 // Do not reset parent
221 Clear(false);
222
223 if (files.isEmpty())
224 return;
225
226 for (const QSharedPointer<ImageItem> & im : std::as_const(files))
227 {
228 // Add image to view
229 m_images.insert(im->m_id, im);
230
231 // Cache all displayed images
232 if (im->IsFile())
233 Cache(im->m_id, im->m_parentId, im->m_url, im->m_thumbNails.at(0).second);
234 }
235
236 if (files.size() == 1 || m_order == kOrdered || m_order == kShuffle)
237 {
238 // Default sequence is ordered
239 for (const QSharedPointer<ImageItem> & im : std::as_const(files))
240 m_sequence.append(im->m_id);
241 }
242
243 if (files.size() > 1)
244 {
245 // Modify viewing sequence
246 if (m_order == kShuffle)
247 {
248 std::shuffle(m_sequence.begin(), m_sequence.end(),
249 std::mt19937(std::random_device()()));
250 }
251 else if (m_order == kRandom)
252 {
253 // An image is not a valid candidate for its successor
254 // add files.size() elements from files in a random order
255 // to m_sequence allowing non-consecutive repetition
256 int size = files.size();
257 int range = files.size() - 1;
258 int last = size; // outside of the random interval [0, size)
259 int count = 0;
260 while (count < size)
261 {
262 int rand = MythRandom(0, range);
263
264 // Avoid consecutive repeats
265 if (last == rand)
266 {
267 continue;
268 }
269 last = rand;
270 m_sequence.append(files.at(rand)->m_id);
271 count++;
272 }
273 }
274 else if (m_order == kSeasonal)
275 {
276 WeightList cdf = CalculateSeasonalWeights(files); // not normalized to 1.0
277 std::vector<uint32_t> weights;
278 weights.reserve(cdf.size());
279 for (int i = 0; i < cdf.size(); i++)
280 {
281 weights.emplace_back(lround(cdf[i] / cdf.back() * UINT32_MAX));
282 }
283 // exclude the last value so the past the end iterator is not returned
284 // by std::upper_bound
285 if (!weights.empty())
286 {
287 uint32_t maxWeight = weights.back() - 1;
288
289 for (int count = 0; count < files.size(); ++count)
290 {
291 uint32_t randWeight = MythRandom(0, maxWeight);
292 auto it = std::upper_bound(weights.begin(), weights.end(), randWeight);
293 int index = std::distance(weights.begin(), it);
294 m_sequence.append(files.at(index)->m_id);
295 }
296 }
297 }
298 }
299}
300
301
313{
314 WeightList weights(files.size());
315 double totalWeight = 0;
316 QDateTime now = QDateTime::currentDateTime();
317
318 for (int i = 0; i < files.size(); ++i)
319 {
320 ImagePtrK im = files.at(i);
321 double weight = 0;
322
323 if (im->m_date == 0s)
324 weight = DEFAULT_WEIGHT;
325 else
326 {
327 QDateTime timestamp = QDateTime::fromSecsSinceEpoch(im->m_date.count());
328 QDateTime curYearAnniversary =
329 QDateTime(QDate(now.date().year(),
330 timestamp.date().month(),
331 timestamp.date().day()),
332 timestamp.time());
333
334 bool isAnniversaryPast = curYearAnniversary < now;
335
336 QDateTime adjacentYearAnniversary =
337 QDateTime(QDate(now.date().year() +
338 (isAnniversaryPast ? 1 : -1),
339 timestamp.date().month(),
340 timestamp.date().day()),
341 timestamp.time());
342
343 double range = llabs(curYearAnniversary.secsTo(
344 adjacentYearAnniversary)) + BETA_CLIP;
345
346 // This calculation is not normalized, because that would require the
347 // beta function, which isn't part of the C++98 libraries. Weights
348 // that aren't normalized work just as well relative to each other.
349 QDateTime d1(isAnniversaryPast ? curYearAnniversary
350 : adjacentYearAnniversary);
351 QDateTime d2(isAnniversaryPast ? adjacentYearAnniversary
352 : curYearAnniversary);
353 weight = std::pow(llabs(now.secsTo(d1) + BETA_CLIP) / range,
355 * std::pow(llabs(now.secsTo(d2) + BETA_CLIP) / range,
357 }
358 totalWeight += weight;
359 weights[i] = totalWeight;
360 }
361 return weights;
362}
363
364
371bool FlatView::LoadFromDb(int parentId)
372{
373 m_parentId = parentId;
374
375 // Load child images of the parent
376 ImageList files;
377 ImageList dirs;
378 m_mgr.GetChildren(m_parentId, files, dirs);
379
380 // Load gallery datastore with current dir
381 Populate(files);
382
383 return !files.isEmpty();
384}
385
386
391{
392 LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared File cache");
393 m_fileCache.clear();
394}
395
396
403QStringList FlatView::ClearImage(int id, bool remove)
404{
405 if (remove)
406 {
407 m_sequence.removeAll(id);
408 m_images.remove(id);
409 }
410
411 QStringList urls;
413
414 if (!file.m_url.isEmpty())
415 urls << file.m_url;
416
417 if (!file.m_thumbUrl.isEmpty())
418 urls << file.m_thumbUrl;
419
420 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from file cache (%2)")
421 .arg(id).arg(urls.join(",")));
422 return urls;
423}
424
425
431{
432 // Rotate sequence so that (first appearance of) specified image is
433 // at offset from front
434 int index = m_sequence.indexOf(id);
435 if (index >= 0)
436 {
437 int first = index % m_sequence.size();
438 if (first > 0)
439 m_sequence = m_sequence.mid(first) + m_sequence.mid(0, first);
440 }
441}
442
443
451void FlatView::Cache(int id, int parent, const QString &url, const QString &thumb)
452{
453 // Cache parent dir so that dir thumbs are updated when a child changes.
454 // Also store urls for image cache cleanup
455 FileCacheEntry cached(parent, url, thumb);
456 m_fileCache.insert(id, cached);
457 LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cached.ToString(id));
458}
459
460
461QString DirCacheEntry::ToString(int id) const
462{
463 QStringList ids;
464 for (const auto & thumb : std::as_const(m_thumbs))
465 ids << QString::number(thumb.first);
466 return QString("Dir %1 (%2, %3) Thumbs %4 (%5) Parent %6")
467 .arg(id).arg(m_fileCount).arg(m_dirCount).arg(ids.join(","))
468 .arg(m_thumbCount).arg(m_parent);
469}
470
471
477 : FlatView(order)
478{
479 m_marked.Clear();
481}
482
483
489{
490 return QString("%1/%2").arg(m_active).arg(m_sequence.size() - 1);
491}
492
493
503{
504 // Determine parent (defaulting to ancestor) & get initial children
505 ImageList files;
506 ImageList dirs;
507 ImagePtr parent;
508 int count = 0;
509 // Root is guaranteed to return at least 1 item
510 while ((count = m_mgr.GetDirectory(parentId, parent, files, dirs)) == 0)
511 {
512 // Fallback if dir no longer exists
513 // Ascend to Gallery for gallery subdirs, Root for device dirs & Gallery
514 parentId = parentId > PHOTO_DB_ID ? PHOTO_DB_ID : GALLERY_DB_ID;
515 }
516
517 SetDirectory(parentId);
518 m_parentId = parentId;
519
520 // No SG & no devices uses special 'empty' screen
521 if (!parent || (parentId == GALLERY_DB_ID && count == 1))
522 {
523 parent.clear();
524 return false;
525 }
526
527 // Populate all subdirs
528 for (const ImagePtr & im : std::as_const(dirs))
529 {
530 if (im)
531 // Load sufficient thumbs from each dir as subsequent dirs may be empty
533 }
534
535 // Populate parent
537 PopulateThumbs(*parent, kMaxFolderThumbnails, files, dirs);
538
539 // Dirs shown before images
540 ImageList images = dirs + files;
541
542 // Validate marked images
543 if (!m_marked.isEmpty())
544 {
545 QSet<int> ids;
546 for (const QSharedPointer<ImageItem> & im : std::as_const(images))
547 ids.insert(im->m_id);
548 m_marked.intersect(ids);
549 }
550
551 // Parent is always first (for navigating up).
552 images.prepend(parent);
553
554 // Preserve current selection before view is destroyed
555 ImagePtrK selected = GetSelected();
556 int activeId = selected ? selected->m_id : 0;
557
558 // Construct view
559 Populate(images);
560
561 // Reinstate selection, falling back to parent
562 Select(activeId);
563
564 return true;
565}
566
567
574void DirectoryView::LoadDirThumbs(ImageItem &parent, int thumbsNeeded, int level)
575{
576 // Use cached data, if available
577 if (PopulateFromCache(parent, thumbsNeeded))
578 return;
579
580 // Load child images & dirs
581 ImageList files;
582 ImageList dirs;
583 m_mgr.GetChildren(parent.m_id, files, dirs);
584
585 PopulateThumbs(parent, thumbsNeeded, files, dirs, level);
586}
587
588
599void DirectoryView::PopulateThumbs(ImageItem &parent, int thumbsNeeded,
600 const ImageList &files, const ImageList &dirs,
601 int level)
602{
603 // Set parent stats
604 parent.m_fileCount = files.size();
605 parent.m_dirCount = dirs.size();
606
607 // Locate user assigned thumb amongst children, if defined
608 ImagePtr userIm;
609 if (parent.m_userThumbnail != 0)
610 {
611 ImageList images = files + dirs;
612 // ImageItem has been explicitly marked Q_DISABLE_COPY
613 for (const ImagePtr & im : std::as_const(images))
614 {
615 if (im && im->m_id == parent.m_userThumbnail)
616 { // cppcheck-suppress useStlAlgorithm
617 userIm = im;
618 break;
619 }
620 }
621 }
622
623 // Children to use as thumbnails
624 ImageList thumbFiles;
625 ImageList thumbDirs;
626
627 if (!userIm)
628 {
629 // Construct multi-thumbnail from all children
630 thumbFiles = files;
631 thumbDirs = dirs;
632 }
633 else if (userIm->IsFile())
634 {
635 thumbFiles.append(userIm);
636 thumbsNeeded = 1;
637 }
638 else
639 {
640 thumbDirs.append(userIm);
641 }
642
643 // Fill parent thumbs from child files first
644 // Whilst they're available fill as many as possible for cache
645#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
646 for (int i = 0; i < std::min(kMaxFolderThumbnails, thumbFiles.size()); ++i)
647#else
648 for (int i = 0; i < std::min(kMaxFolderThumbnails, static_cast<int>(thumbFiles.size())); ++i)
649#endif
650 {
651 parent.m_thumbNails.append(thumbFiles.at(i)->m_thumbNails.at(0));
652 --thumbsNeeded;
653 }
654
655 // Only recurse if necessary
656 if (thumbsNeeded > 0)
657 {
658 // Prevent lengthy/infinite recursion due to deep/cyclic folder
659 // structures
660 if (++level > 10)
661 {
662 LOG(VB_GENERAL, LOG_NOTICE, LOC +
663 "Directory thumbnails are more than 10 levels deep");
664 }
665 else
666 {
667 // Recursively load subdir thumbs to try to get 1 thumb from each
668 for (const ImagePtr & im : std::as_const(thumbDirs))
669 {
670 if (!im)
671 continue;
672
673 // Load sufficient thumbs from each dir as subsequent dirs may
674 // be empty
675 LoadDirThumbs(*im, thumbsNeeded, level);
676
677 if (!im->m_thumbNails.empty())
678 {
679 // Add first thumbnail to parent thumb
680 parent.m_thumbNails.append(im->m_thumbNails.at(0));
681
682 // Quit when we have sufficient thumbs
683 if (--thumbsNeeded == 0)
684 break;
685 }
686 }
687
688 // If insufficient dirs to supply 1 thumb per dir, use other dir
689 // thumbs (indices 1-3) as well
690 int i = 0;
691 while (thumbsNeeded > 0 && ++i < kMaxFolderThumbnails)
692 {
693 for (const QSharedPointer<ImageItem> & im : std::as_const(thumbDirs))
694 {
695 if (i < im->m_thumbNails.size())
696 {
697 parent.m_thumbNails.append(im->m_thumbNails.at(i));
698 if (--thumbsNeeded == 0)
699 break;
700 }
701 }
702 }
703 }
704 }
705
706 // Flag the cached entry with number of thumbs loaded. If future uses require
707 // more, then the dir must be reloaded.
708 // For user thumbs and dirs with insufficient child images, the cache is always valid
709 int scanned = (userIm || thumbsNeeded > 0)
711 : parent.m_thumbNails.size();
712
713 // Cache result to optimize navigation
714 Cache(parent, scanned);
715}
716
717
722void DirectoryView::Clear(bool /*resetParent*/)
723{
724 ClearMarked();
725 ClearCache();
727}
728
729
734{
735 // Any marking clears previous marks
738}
739
740
746void DirectoryView::Mark(int id, bool mark)
747{
748 if (mark)
749 {
750 // Any marking clears previous marks
752 m_marked.Add(id);
753 }
754 else
755 {
756 m_prevMarked.remove(id);
757 m_marked.remove(id);
758 }
759}
760
761
766{
767 // Any marking clears previous marks
770}
771
772
777{
778 m_marked.Clear();
780}
781
782
788{
789 if (m_marked.IsFor(newParent))
790 // Directory hasn't changed
791 return;
792
793 // Markings are cleared on every dir change
794 // Any current markings become previous markings
795 // Only 1 set of previous markings are preserved
796 if (m_prevMarked.IsFor(newParent))
797 {
798 // Returned to dir of previous markings: reinstate them
801 return;
802 }
803
804 if (!m_marked.isEmpty())
805 // Preserve current markings
807
808 // Initialise current markings for new dir
809 m_marked.Initialise(newParent);
810}
811
812
818{
819 // hiddenMarked is true if 1 or more marked items are hidden
820 // unhiddenMarked is true if 1 or more marked items are not hidden
821 bool hiddenMarked = false;
822 bool unhiddenMarked = false;
823 for (int id : std::as_const(m_marked))
824 {
825 ImagePtrK im = m_images.value(id);
826 if (!im)
827 continue;
828
829 if (im->m_isHidden)
830 hiddenMarked = true;
831 else
832 unhiddenMarked = true;
833
834 if (hiddenMarked && unhiddenMarked)
835 break;
836 }
837
838 return {GetSelected(), m_sequence.size() - 1,
840 hiddenMarked, unhiddenMarked};
841}
842
843
851{
852 DirCacheEntry cached(m_dirCache.value(dir.m_id));
853 if (cached.m_dirCount == -1 || cached.m_thumbCount < required)
854 return false;
855
856 dir.m_fileCount = cached.m_fileCount;
857 dir.m_dirCount = cached.m_dirCount;
858 dir.m_thumbNails = cached.m_thumbs;
859
860 LOG(VB_FILE, LOG_DEBUG, LOC + "Using cached " + cached.ToString(dir.m_id));
861 return true;
862}
863
864
870void DirectoryView::Cache(ImageItemK &dir, int thumbCount)
871{
872 // Cache counts & thumbnails for each dir so that we don't need to reload its
873 // children from Db each time it's displayed
874 DirCacheEntry cacheEntry(dir.m_parentId, dir.m_dirCount, dir.m_fileCount,
875 dir.m_thumbNails, thumbCount);
876
877 m_dirCache.insert(dir.m_id, cacheEntry);
878
879 // Cache images used by dir thumbnails
880 for (const ThumbPair & thumb : std::as_const(dir.m_thumbNails))
881 {
882 // Do not overwrite any existing image url nor parent.
883 // Image url is cached when image is displayed as a child, but not as a
884 // ancestor dir thumbnail
885 // First cache attempt will be by parent. Subsequent attempts may be
886 // by ancestor dirs.
887 if (!m_fileCache.contains(thumb.first))
888 FlatView::Cache(thumb.first, dir.m_id, "", thumb.second);
889 }
890 LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cacheEntry.ToString(dir.m_id));
891}
892
893
898{
899 LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared Dir cache");
900 m_dirCache.clear();
902}
903
904
912QStringList DirectoryView::RemoveImage(int id, bool deleted)
913{
914 QStringList urls;
915 int dirId = id;
916
917 if (deleted)
918 {
919 m_marked.remove(id);
920 m_prevMarked.remove(id);
921 }
922
923 // If id is a file then start with its parent
924 if (m_fileCache.contains(id))
925 {
926 // Clear file cache & start from its parent dir
927 dirId = m_fileCache.value(id).m_parent;
928 urls = FlatView::ClearImage(id, deleted);
929 }
930
931 // Clear ancestor dirs
932 while (m_dirCache.contains(dirId))
933 {
934 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from dir cache").arg(dirId));
935 DirCacheEntry dir = m_dirCache.take(dirId);
936 dirId = dir.m_parent;
937 }
938 return urls;
939}
940
941
949bool TreeView::LoadFromDb(int parentId)
950{
951 m_parentId = parentId;
952
953 // Load visible subtree of the parent
954 // Ordered images of parent first, then breadth-first recursion of ordered dirs
955 ImageList files;
957
958 // Load view
959 Populate(files);
960
961 return !files.isEmpty();
962}
Records dir info for every displayed dir.
Definition: galleryviews.h:149
QString ToString(int id) const
QList< ThumbPair > m_thumbs
Definition: galleryviews.h:163
void LoadDirThumbs(ImageItem &parent, int thumbsNeeded, int level=0)
Populate thumbs for a dir.
QString GetPosition() const
Get positional status.
void ClearMarked()
Unmark all items.
void Clear(bool resetParent=true)
Resets view.
bool PopulateFromCache(ImageItem &dir, int required)
Retrieve cached dir, if available.
MenuSubjects GetMenuSubjects()
Determine current selection, markings & various info to support menu display.
void PopulateThumbs(ImageItem &parent, int thumbsNeeded, const ImageList &files, const ImageList &dirs, int level=0)
Populate directory stats & thumbnails recursively from database as follows: Use user cover,...
QHash< int, DirCacheEntry > m_dirCache
Caches displayed image dirs.
Definition: galleryviews.h:208
DirectoryView(SlideOrderType order)
Constructs a view of images & directories that can be marked.
void MarkAll()
Mark all images/dirs.
bool LoadFromDb(int parentId) override
Populate view from database as images/subdirs of a directory. View is ordered: Parent dir,...
void ClearCache()
Clears UI cache.
MarkedFiles m_prevMarked
Marked items in previous dir.
Definition: galleryviews.h:205
ImageIdList GetChildren() const
Definition: galleryviews.h:200
QStringList RemoveImage(int id, bool deleted=false)
Clear file/dir and all its ancestors from UI cache so that ancestor thumbnails are recalculated....
void InvertMarked()
Mark all unmarked items, unmark all marked items.
MarkedFiles m_marked
Marked items in current dir/view.
Definition: galleryviews.h:204
void SetDirectory(int newParent)
Manage markings on tree navigation.
void Cache(ImageItemK &dir, int thumbCount)
Cache displayed dir.
void Mark(int id, bool mark)
Mark/unmark an image/dir.
Records info of displayed image files to enable clean-up of the UI image cache.
Definition: galleryviews.h:80
QString ToString(int id) const
Definition: galleryviews.h:87
A datastore of images for display by a screen.
Definition: galleryviews.h:102
void Cache(int id, int parent, const QString &url, const QString &thumb)
Cache image properties to optimize UI.
bool Update(int id)
Updates view with images that have been updated.
int m_parentId
Definition: galleryviews.h:133
QStringList ClearImage(int id, bool remove=false)
Clear file from UI cache and optionally from view.
SlideOrderType m_order
Definition: galleryviews.h:134
void ClearCache()
Clears UI cache.
ImagePtrK Prev(int inc)
Decrements iterator and returns previous image. Wraps at start.
bool Select(int id, int fallback=0)
Selects first occurrence of an image.
ImageManagerFe & m_mgr
Definition: galleryviews.h:135
void Populate(ImageList &files)
Fills view with Db images, re-ordering them as required.
ImagePtrK HasNext(int inc) const
Peeks at next image in view but does not advance iterator.
void Clear(bool resetParent=true)
Reset view.
int m_active
Sequence index of current selected image.
Definition: galleryviews.h:138
ImagePtrK Next(int inc)
Advance iterator and return next image, wrapping if necessary. Regenerates unordered views on wrap.
QHash< int, FileCacheEntry > m_fileCache
Caches displayed image files.
Definition: galleryviews.h:141
ImageIdList m_sequence
The sequence in which to display images.
Definition: galleryviews.h:137
QString GetPosition() const
Get positional status.
ImagePtrK GetSelected() const
Get current selection.
virtual bool LoadFromDb(int parentId)
Populate view with database images from a directory.
ImageListK GetAllNodes() const
Get all images/dirs in view.
ImagePtrK HasPrev(int inc) const
Peeks at previous image in view but does not decrement iterator.
QHash< int, ImagePtrK > m_images
Image objects currently displayed.
Definition: galleryviews.h:136
void Rotate(int id)
Rotate view so that starting image is at front.
static WeightList CalculateSeasonalWeights(ImageList &files)
This method calculates a weight for the item based on how closely it was taken to the current time of...
int GetDirectory(int id, ImagePtr &parent, ImageList &files, ImageList &dirs) const
Return images (local and/or remote) for a dir and its direct children.
int GetImages(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Returns images (local or remote but not a combination)
void GetImageTree(int id, ImageList &files) const
Return all files (local or remote) in the sub-trees of a dir.
int GetChildren(int id, ImageList &files, ImageList &dirs) const
Return (local or remote) images that are direct children of a dir.
Represents a picture, video or directory.
Definition: imagetypes.h:69
int m_id
Uniquely identifies an image (file/dir).
Definition: imagetypes.h:89
QList< ThumbPair > m_thumbNails
Definition: imagetypes.h:111
int m_fileCount
Number of child images (dirs only)
Definition: imagetypes.h:113
int m_dirCount
Id & URLs of thumbnail(s). 1 for a file, 4 for dirs.
Definition: imagetypes.h:112
int m_parentId
Id of parent dir.
Definition: imagetypes.h:96
int m_userThumbnail
Id of thumbnail to use as cover (dirs only)
Definition: imagetypes.h:106
void Initialise(int id)
Definition: galleryviews.h:41
bool IsFor(int id) const
Definition: galleryviews.h:43
void Add(const ImageIdList &newIds)
void Invert(const ImageIdList &all)
void Clear()
Definition: galleryviews.h:42
A snapshot of current selection, markings & dir info when menu is invoked.
Definition: galleryviews.h:56
bool LoadFromDb(int parentId) override
Populate view from database as images of a directory sub-tree. Default order of a tree is depth-first...
static constexpr qint64 BETA_CLIP
The edges of the distribution get clipped to avoid a singularity.
#define LOC
const double TRAILING_BETA_SHAPE
See LEADING_BETA_SHAPE.
const double DEFAULT_WEIGHT
Photos without an exif timestamp will default to the mode of the beta distribution.
static const int kMaxFolderThumbnails
Number of thumbnails to use for folders.
const double LEADING_BETA_SHAPE
Tuning parameter for seasonal weights, between 0 and 1, where lower numbers give greater weight to se...
Provides view datastores for Gallery screens.
SlideOrderType
Order of images in slideshow.
Definition: galleryviews.h:24
@ kSeasonal
Biased random selection so that images are more likely to appear on anniversaries.
Definition: galleryviews.h:28
@ kShuffle
Each image appears exactly once, but in random order.
Definition: galleryviews.h:26
@ kRandom
Random selection from view. An image may be absent or appear multiple times.
Definition: galleryviews.h:27
@ kOrdered
Ordered as per user setting GallerySortOrder.
Definition: galleryviews.h:25
QVector< double > WeightList
Seasonal weightings for images in a view.
Definition: galleryviews.h:33
static guint32 * tmp
Definition: goom_core.cpp:26
QVector< ImagePtr > ImageList
Definition: imagetypes.h:160
QList< ImagePtrK > ImageListK
Definition: imagetypes.h:166
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:165
QPair< int, QString > ThumbPair
Definition: imagetypes.h:64
static constexpr int GALLERY_DB_ID
Definition: imagetypes.h:27
static constexpr int PHOTO_DB_ID
Definition: imagetypes.h:29
QSharedPointer< ImageItem > ImagePtr
Definition: imagetypes.h:159
QList< int > ImageIdList
Definition: imagetypes.h:60
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
Convenience inline random number generator functions.
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
uint32_t MythRandom()
generate 32 random bits
Definition: mythrandom.h:20