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::ranges::upper_bound(weights, 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 {
325 weight = DEFAULT_WEIGHT;
326 }
327 else
328 {
329 QDateTime timestamp = QDateTime::fromSecsSinceEpoch(im->m_date.count());
330 QDateTime curYearAnniversary =
331 QDateTime(QDate(now.date().year(),
332 timestamp.date().month(),
333 timestamp.date().day()),
334 timestamp.time());
335
336 bool isAnniversaryPast = curYearAnniversary < now;
337
338 QDateTime adjacentYearAnniversary =
339 QDateTime(QDate(now.date().year() +
340 (isAnniversaryPast ? 1 : -1),
341 timestamp.date().month(),
342 timestamp.date().day()),
343 timestamp.time());
344
345 double range = llabs(curYearAnniversary.secsTo(
346 adjacentYearAnniversary)) + BETA_CLIP;
347
348 // This calculation is not normalized, because that would require the
349 // beta function, which isn't part of the C++98 libraries. Weights
350 // that aren't normalized work just as well relative to each other.
351 QDateTime d1(isAnniversaryPast ? curYearAnniversary
352 : adjacentYearAnniversary);
353 QDateTime d2(isAnniversaryPast ? adjacentYearAnniversary
354 : curYearAnniversary);
355 weight = std::pow(llabs(now.secsTo(d1) + BETA_CLIP) / range,
357 * std::pow(llabs(now.secsTo(d2) + BETA_CLIP) / range,
359 }
360 totalWeight += weight;
361 weights[i] = totalWeight;
362 }
363 return weights;
364}
365
366
373bool FlatView::LoadFromDb(int parentId)
374{
375 m_parentId = parentId;
376
377 // Load child images of the parent
378 ImageList files;
379 ImageList dirs;
380 m_mgr.GetChildren(m_parentId, files, dirs);
381
382 // Load gallery datastore with current dir
383 Populate(files);
384
385 return !files.isEmpty();
386}
387
388
393{
394 LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared File cache");
395 m_fileCache.clear();
396}
397
398
405QStringList FlatView::ClearImage(int id, bool remove)
406{
407 if (remove)
408 {
409 m_sequence.removeAll(id);
410 m_images.remove(id);
411 }
412
413 QStringList urls;
415
416 if (!file.m_url.isEmpty())
417 urls << file.m_url;
418
419 if (!file.m_thumbUrl.isEmpty())
420 urls << file.m_thumbUrl;
421
422 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from file cache (%2)")
423 .arg(id).arg(urls.join(",")));
424 return urls;
425}
426
427
433{
434 // Rotate sequence so that (first appearance of) specified image is
435 // at offset from front
436 int index = m_sequence.indexOf(id);
437 if (index >= 0)
438 {
439 int first = index % m_sequence.size();
440 if (first > 0)
441 m_sequence = m_sequence.mid(first) + m_sequence.mid(0, first);
442 }
443}
444
445
453void FlatView::Cache(int id, int parent, const QString &url, const QString &thumb)
454{
455 // Cache parent dir so that dir thumbs are updated when a child changes.
456 // Also store urls for image cache cleanup
457 FileCacheEntry cached(parent, url, thumb);
458 m_fileCache.insert(id, cached);
459 LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cached.ToString(id));
460}
461
462
463QString DirCacheEntry::ToString(int id) const
464{
465 QStringList ids;
466 for (const auto & thumb : std::as_const(m_thumbs))
467 ids << QString::number(thumb.first);
468 return QString("Dir %1 (%2, %3) Thumbs %4 (%5) Parent %6")
469 .arg(id).arg(m_fileCount).arg(m_dirCount).arg(ids.join(","))
470 .arg(m_thumbCount).arg(m_parent);
471}
472
473
479 : FlatView(order)
480{
481 m_marked.Clear();
483}
484
485
491{
492 return QString("%1/%2").arg(m_active).arg(m_sequence.size() - 1);
493}
494
495
505{
506 // Determine parent (defaulting to ancestor) & get initial children
507 ImageList files;
508 ImageList dirs;
509 ImagePtr parent;
510 int count = 0;
511 // Root is guaranteed to return at least 1 item
512 while ((count = m_mgr.GetDirectory(parentId, parent, files, dirs)) == 0)
513 {
514 // Fallback if dir no longer exists
515 // Ascend to Gallery for gallery subdirs, Root for device dirs & Gallery
516 parentId = parentId > PHOTO_DB_ID ? PHOTO_DB_ID : GALLERY_DB_ID;
517 }
518
519 SetDirectory(parentId);
520 m_parentId = parentId;
521
522 // No SG & no devices uses special 'empty' screen
523 if (!parent || (parentId == GALLERY_DB_ID && count == 1))
524 {
525 parent.clear();
526 return false;
527 }
528
529 // Populate all subdirs
530 for (const ImagePtr & im : std::as_const(dirs))
531 {
532 if (im)
533 // Load sufficient thumbs from each dir as subsequent dirs may be empty
535 }
536
537 // Populate parent
539 PopulateThumbs(*parent, kMaxFolderThumbnails, files, dirs);
540
541 // Dirs shown before images
542 ImageList images = dirs + files;
543
544 // Validate marked images
545 if (!m_marked.isEmpty())
546 {
547 QSet<int> ids;
548 for (const QSharedPointer<ImageItem> & im : std::as_const(images))
549 ids.insert(im->m_id);
550 m_marked.intersect(ids);
551 }
552
553 // Parent is always first (for navigating up).
554 images.prepend(parent);
555
556 // Preserve current selection before view is destroyed
557 ImagePtrK selected = GetSelected();
558 int activeId = selected ? selected->m_id : 0;
559
560 // Construct view
561 Populate(images);
562
563 // Reinstate selection, falling back to parent
564 Select(activeId);
565
566 return true;
567}
568
569
576void DirectoryView::LoadDirThumbs(ImageItem &parent, int thumbsNeeded, int level)
577{
578 // Use cached data, if available
579 if (PopulateFromCache(parent, thumbsNeeded))
580 return;
581
582 // Load child images & dirs
583 ImageList files;
584 ImageList dirs;
585 m_mgr.GetChildren(parent.m_id, files, dirs);
586
587 PopulateThumbs(parent, thumbsNeeded, files, dirs, level);
588}
589
590
601void DirectoryView::PopulateThumbs(ImageItem &parent, int thumbsNeeded,
602 const ImageList &files, const ImageList &dirs,
603 int level)
604{
605 // Set parent stats
606 parent.m_fileCount = files.size();
607 parent.m_dirCount = dirs.size();
608
609 // Locate user assigned thumb amongst children, if defined
610 ImagePtr userIm;
611 if (parent.m_userThumbnail != 0)
612 {
613 ImageList images = files + dirs;
614 // ImageItem has been explicitly marked Q_DISABLE_COPY
615 for (const ImagePtr & im : std::as_const(images))
616 {
617 if (im && im->m_id == parent.m_userThumbnail)
618 { // cppcheck-suppress useStlAlgorithm
619 userIm = im;
620 break;
621 }
622 }
623 }
624
625 // Children to use as thumbnails
626 ImageList thumbFiles;
627 ImageList thumbDirs;
628
629 if (!userIm)
630 {
631 // Construct multi-thumbnail from all children
632 thumbFiles = files;
633 thumbDirs = dirs;
634 }
635 else if (userIm->IsFile())
636 {
637 thumbFiles.append(userIm);
638 thumbsNeeded = 1;
639 }
640 else
641 {
642 thumbDirs.append(userIm);
643 }
644
645 // Fill parent thumbs from child files first
646 // Whilst they're available fill as many as possible for cache
647#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
648 for (int i = 0; i < std::min(kMaxFolderThumbnails, thumbFiles.size()); ++i)
649#else
650 for (int i = 0; i < std::min(kMaxFolderThumbnails, static_cast<int>(thumbFiles.size())); ++i)
651#endif
652 {
653 parent.m_thumbNails.append(thumbFiles.at(i)->m_thumbNails.at(0));
654 --thumbsNeeded;
655 }
656
657 // Only recurse if necessary
658 if (thumbsNeeded > 0)
659 {
660 // Prevent lengthy/infinite recursion due to deep/cyclic folder
661 // structures
662 if (++level > 10)
663 {
664 LOG(VB_GENERAL, LOG_NOTICE, LOC +
665 "Directory thumbnails are more than 10 levels deep");
666 }
667 else
668 {
669 // Recursively load subdir thumbs to try to get 1 thumb from each
670 for (const ImagePtr & im : std::as_const(thumbDirs))
671 {
672 if (!im)
673 continue;
674
675 // Load sufficient thumbs from each dir as subsequent dirs may
676 // be empty
677 LoadDirThumbs(*im, thumbsNeeded, level);
678
679 if (!im->m_thumbNails.empty())
680 {
681 // Add first thumbnail to parent thumb
682 parent.m_thumbNails.append(im->m_thumbNails.at(0));
683
684 // Quit when we have sufficient thumbs
685 if (--thumbsNeeded == 0)
686 break;
687 }
688 }
689
690 // If insufficient dirs to supply 1 thumb per dir, use other dir
691 // thumbs (indices 1-3) as well
692 int i = 0;
693 while (thumbsNeeded > 0 && ++i < kMaxFolderThumbnails)
694 {
695 for (const QSharedPointer<ImageItem> & im : std::as_const(thumbDirs))
696 {
697 if (i < im->m_thumbNails.size())
698 {
699 parent.m_thumbNails.append(im->m_thumbNails.at(i));
700 if (--thumbsNeeded == 0)
701 break;
702 }
703 }
704 }
705 }
706 }
707
708 // Flag the cached entry with number of thumbs loaded. If future uses require
709 // more, then the dir must be reloaded.
710 // For user thumbs and dirs with insufficient child images, the cache is always valid
711 int scanned = (userIm || thumbsNeeded > 0)
713 : parent.m_thumbNails.size();
714
715 // Cache result to optimize navigation
716 Cache(parent, scanned);
717}
718
719
724void DirectoryView::Clear(bool /*resetParent*/)
725{
726 ClearMarked();
727 ClearCache();
729}
730
731
736{
737 // Any marking clears previous marks
740}
741
742
748void DirectoryView::Mark(int id, bool mark)
749{
750 if (mark)
751 {
752 // Any marking clears previous marks
754 m_marked.Add(id);
755 }
756 else
757 {
758 m_prevMarked.remove(id);
759 m_marked.remove(id);
760 }
761}
762
763
768{
769 // Any marking clears previous marks
772}
773
774
779{
780 m_marked.Clear();
782}
783
784
790{
791 if (m_marked.IsFor(newParent))
792 // Directory hasn't changed
793 return;
794
795 // Markings are cleared on every dir change
796 // Any current markings become previous markings
797 // Only 1 set of previous markings are preserved
798 if (m_prevMarked.IsFor(newParent))
799 {
800 // Returned to dir of previous markings: reinstate them
803 return;
804 }
805
806 if (!m_marked.isEmpty())
807 // Preserve current markings
809
810 // Initialise current markings for new dir
811 m_marked.Initialise(newParent);
812}
813
814
820{
821 // hiddenMarked is true if 1 or more marked items are hidden
822 // unhiddenMarked is true if 1 or more marked items are not hidden
823 bool hiddenMarked = false;
824 bool unhiddenMarked = false;
825 for (int id : std::as_const(m_marked))
826 {
827 ImagePtrK im = m_images.value(id);
828 if (!im)
829 continue;
830
831 if (im->m_isHidden)
832 hiddenMarked = true;
833 else
834 unhiddenMarked = true;
835
836 if (hiddenMarked && unhiddenMarked)
837 break;
838 }
839
840 return {GetSelected(), m_sequence.size() - 1,
842 hiddenMarked, unhiddenMarked};
843}
844
845
853{
854 DirCacheEntry cached(m_dirCache.value(dir.m_id));
855 if (cached.m_dirCount == -1 || cached.m_thumbCount < required)
856 return false;
857
858 dir.m_fileCount = cached.m_fileCount;
859 dir.m_dirCount = cached.m_dirCount;
860 dir.m_thumbNails = cached.m_thumbs;
861
862 LOG(VB_FILE, LOG_DEBUG, LOC + "Using cached " + cached.ToString(dir.m_id));
863 return true;
864}
865
866
872void DirectoryView::Cache(ImageItemK &dir, int thumbCount)
873{
874 // Cache counts & thumbnails for each dir so that we don't need to reload its
875 // children from Db each time it's displayed
876 DirCacheEntry cacheEntry(dir.m_parentId, dir.m_dirCount, dir.m_fileCount,
877 dir.m_thumbNails, thumbCount);
878
879 m_dirCache.insert(dir.m_id, cacheEntry);
880
881 // Cache images used by dir thumbnails
882 for (const ThumbPair & thumb : std::as_const(dir.m_thumbNails))
883 {
884 // Do not overwrite any existing image url nor parent.
885 // Image url is cached when image is displayed as a child, but not as a
886 // ancestor dir thumbnail
887 // First cache attempt will be by parent. Subsequent attempts may be
888 // by ancestor dirs.
889 if (!m_fileCache.contains(thumb.first))
890 FlatView::Cache(thumb.first, dir.m_id, "", thumb.second);
891 }
892 LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cacheEntry.ToString(dir.m_id));
893}
894
895
900{
901 LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared Dir cache");
902 m_dirCache.clear();
904}
905
906
914QStringList DirectoryView::RemoveImage(int id, bool deleted)
915{
916 QStringList urls;
917 int dirId = id;
918
919 if (deleted)
920 {
921 m_marked.remove(id);
922 m_prevMarked.remove(id);
923 }
924
925 // If id is a file then start with its parent
926 if (m_fileCache.contains(id))
927 {
928 // Clear file cache & start from its parent dir
929 dirId = m_fileCache.value(id).m_parent;
930 urls = FlatView::ClearImage(id, deleted);
931 }
932
933 // Clear ancestor dirs
934 while (m_dirCache.contains(dirId))
935 {
936 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from dir cache").arg(dirId));
937 DirCacheEntry dir = m_dirCache.take(dirId);
938 dirId = dir.m_parent;
939 }
940 return urls;
941}
942
943
951bool TreeView::LoadFromDb(int parentId)
952{
953 m_parentId = parentId;
954
955 // Load visible subtree of the parent
956 // Ordered images of parent first, then breadth-first recursion of ordered dirs
957 ImageList files;
959
960 // Load view
961 Populate(files);
962
963 return !files.isEmpty();
964}
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
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