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 files.reserve(m_sequence.size());
58 for (int id : std::as_const(m_sequence))
59 files.append(m_images.value(id));
60 return files;
61}
62
63
69{
70 return m_active < 0 || m_active >= m_sequence.size()
71 ? ImagePtrK() : m_images.value(m_sequence.at(m_active));
72}
73
74
79QString FlatView::GetPosition() const
80{
81 return QString("%1/%2").arg(m_active + 1).arg(m_sequence.size());
82}
83
84
90bool FlatView::Update(int id)
91{
92 ImagePtrK im = m_images.value(id);
93 if (!im)
94 return false;
95
96 // Get updated image
97 ImageList files;
98 ImageList dirs;
99 ImageIdList ids = ImageIdList() << id;
100 if (m_mgr.GetImages(ids, files, dirs) != 1 || files.size() != 1)
101 return false;
102
103 bool active = (im == GetSelected());
104
105 // Replace image
106 m_images.insert(id, files.at(0));
107
108 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Modified id %1").arg(id));
109
110 return active;
111}
112
113
121bool FlatView::Select(int id, int fallback)
122{
123 // Select first appearance of image
124 int index = m_sequence.indexOf(id);
125 if (index >= 0)
126 {
127 m_active = index;
128 return true;
129 }
130
131 if (fallback >= 0)
132 m_active = fallback;
133
134 return false;
135}
136
137
142void FlatView::Clear(bool resetParent)
143{
144 m_images.clear();
145 m_sequence.clear();
146 m_active = -1;
147 if (resetParent)
149}
150
151
157{
158 return m_sequence.isEmpty() || m_active + inc >= m_sequence.size()
159 ? ImagePtrK() : m_images.value(m_sequence.at(m_active + inc));
160}
161
162
169{
170 if (m_sequence.isEmpty())
171 return {};
172
173 // Preserve index as it may be reset when wrapping
174 int next = m_active + inc;
175
176 // Regenerate unordered views when wrapping
177 if (next >= m_sequence.size() && m_order != kOrdered && !LoadFromDb(m_parentId))
178 // Images have disappeared
179 return {};
180
181 m_active = next % m_sequence.size();
182 return m_images.value(m_sequence.at(m_active));
183}
184
185
191{
192 return m_sequence.isEmpty() || m_active < inc
193 ? ImagePtrK() : m_images.value(m_sequence.at(m_active - inc));
194}
195
196
202{
203 if (m_sequence.isEmpty())
204 return {};
205
206 // Wrap avoiding modulo of negative uncertainty
207 m_active -= inc % m_sequence.size();
208 if (m_active < 0)
209 m_active += m_sequence.size();
210
211 return m_images.value(m_sequence.at(m_active));
212}
213
214
220{
221 // Do not reset parent
222 Clear(false);
223
224 if (files.isEmpty())
225 return;
226
227 for (const QSharedPointer<ImageItem> & im : std::as_const(files))
228 {
229 // Add image to view
230 m_images.insert(im->m_id, im);
231
232 // Cache all displayed images
233 if (im->IsFile())
234 Cache(im->m_id, im->m_parentId, im->m_url, im->m_thumbNails.at(0).second);
235 }
236
237 if (files.size() == 1 || m_order == kOrdered || m_order == kShuffle)
238 {
239 // Default sequence is ordered
240 for (const QSharedPointer<ImageItem> & im : std::as_const(files))
241 m_sequence.append(im->m_id);
242 }
243
244 if (files.size() > 1)
245 {
246 // Modify viewing sequence
247 if (m_order == kShuffle)
248 {
249 std::shuffle(m_sequence.begin(), m_sequence.end(),
250 std::mt19937(std::random_device()()));
251 }
252 else if (m_order == kRandom)
253 {
254 // An image is not a valid candidate for its successor
255 // add files.size() elements from files in a random order
256 // to m_sequence allowing non-consecutive repetition
257 int size = files.size();
258 int range = files.size() - 1;
259 int last = size; // outside of the random interval [0, size)
260 int count = 0;
261 while (count < size)
262 {
263 int rand = MythRandom(0, range);
264
265 // Avoid consecutive repeats
266 if (last == rand)
267 {
268 continue;
269 }
270 last = rand;
271 m_sequence.append(files.at(rand)->m_id);
272 count++;
273 }
274 }
275 else if (m_order == kSeasonal)
276 {
277 WeightList cdf = CalculateSeasonalWeights(files); // not normalized to 1.0
278 std::vector<uint32_t> weights;
279 weights.reserve(cdf.size());
280 for (int i = 0; i < cdf.size(); i++)
281 {
282 weights.emplace_back(lround(cdf[i] / cdf.back() * UINT32_MAX));
283 }
284 // exclude the last value so the past the end iterator is not returned
285 // by std::upper_bound
286 if (!weights.empty())
287 {
288 uint32_t maxWeight = weights.back() - 1;
289
290 for (int count = 0; count < files.size(); ++count)
291 {
292 uint32_t randWeight = MythRandom(0, maxWeight);
293 auto it = std::ranges::upper_bound(weights, randWeight);
294 int index = std::distance(weights.begin(), it);
295 m_sequence.append(files.at(index)->m_id);
296 }
297 }
298 }
299 }
300}
301
302
314{
315 WeightList weights(files.size());
316 double totalWeight = 0;
317 QDateTime now = QDateTime::currentDateTime();
318
319 for (int i = 0; i < files.size(); ++i)
320 {
321 ImagePtrK im = files.at(i);
322 double weight = 0;
323
324 if (im->m_date == 0s)
325 {
326 weight = DEFAULT_WEIGHT;
327 }
328 else
329 {
330 QDateTime timestamp = QDateTime::fromSecsSinceEpoch(im->m_date.count());
331 QDateTime curYearAnniversary =
332 QDateTime(QDate(now.date().year(),
333 timestamp.date().month(),
334 timestamp.date().day()),
335 timestamp.time());
336
337 bool isAnniversaryPast = curYearAnniversary < now;
338
339 QDateTime adjacentYearAnniversary =
340 QDateTime(QDate(now.date().year() +
341 (isAnniversaryPast ? 1 : -1),
342 timestamp.date().month(),
343 timestamp.date().day()),
344 timestamp.time());
345
346 double range = llabs(curYearAnniversary.secsTo(
347 adjacentYearAnniversary)) + BETA_CLIP;
348
349 // This calculation is not normalized, because that would require the
350 // beta function, which isn't part of the C++98 libraries. Weights
351 // that aren't normalized work just as well relative to each other.
352 QDateTime d1(isAnniversaryPast ? curYearAnniversary
353 : adjacentYearAnniversary);
354 QDateTime d2(isAnniversaryPast ? adjacentYearAnniversary
355 : curYearAnniversary);
356 weight = std::pow(llabs(now.secsTo(d1) + BETA_CLIP) / range,
358 * std::pow(llabs(now.secsTo(d2) + BETA_CLIP) / range,
360 }
361 totalWeight += weight;
362 weights[i] = totalWeight;
363 }
364 return weights;
365}
366
367
374bool FlatView::LoadFromDb(int parentId)
375{
376 m_parentId = parentId;
377
378 // Load child images of the parent
379 ImageList files;
380 ImageList dirs;
381 m_mgr.GetChildren(m_parentId, files, dirs);
382
383 // Load gallery datastore with current dir
384 Populate(files);
385
386 return !files.isEmpty();
387}
388
389
394{
395 LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared File cache");
396 m_fileCache.clear();
397}
398
399
406QStringList FlatView::ClearImage(int id, bool remove)
407{
408 if (remove)
409 {
410 m_sequence.removeAll(id);
411 m_images.remove(id);
412 }
413
414 QStringList urls;
416
417 if (!file.m_url.isEmpty())
418 urls << file.m_url;
419
420 if (!file.m_thumbUrl.isEmpty())
421 urls << file.m_thumbUrl;
422
423 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from file cache (%2)")
424 .arg(id).arg(urls.join(",")));
425 return urls;
426}
427
428
434{
435 // Rotate sequence so that (first appearance of) specified image is
436 // at offset from front
437 int index = m_sequence.indexOf(id);
438 if (index >= 0)
439 {
440 int first = index % m_sequence.size();
441 if (first > 0)
442 m_sequence = m_sequence.mid(first) + m_sequence.mid(0, first);
443 }
444}
445
446
454void FlatView::Cache(int id, int parent, const QString &url, const QString &thumb)
455{
456 // Cache parent dir so that dir thumbs are updated when a child changes.
457 // Also store urls for image cache cleanup
458 FileCacheEntry cached(parent, url, thumb);
459 m_fileCache.insert(id, cached);
460 LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cached.ToString(id));
461}
462
463
464QString DirCacheEntry::ToString(int id) const
465{
466 QStringList ids;
467 ids.reserve(m_thumbs.size());
468 for (const auto & thumb : std::as_const(m_thumbs))
469 ids << QString::number(thumb.first);
470 return QString("Dir %1 (%2, %3) Thumbs %4 (%5) Parent %6")
471 .arg(id).arg(m_fileCount).arg(m_dirCount).arg(ids.join(","))
472 .arg(m_thumbCount).arg(m_parent);
473}
474
475
481 : FlatView(order)
482{
483 m_marked.Clear();
485}
486
487
493{
494 return QString("%1/%2").arg(m_active).arg(m_sequence.size() - 1);
495}
496
497
507{
508 // Determine parent (defaulting to ancestor) & get initial children
509 ImageList files;
510 ImageList dirs;
511 ImagePtr parent;
512 int count = 0;
513 // Root is guaranteed to return at least 1 item
514 while ((count = m_mgr.GetDirectory(parentId, parent, files, dirs)) == 0)
515 {
516 // Fallback if dir no longer exists
517 // Ascend to Gallery for gallery subdirs, Root for device dirs & Gallery
518 parentId = parentId > PHOTO_DB_ID ? PHOTO_DB_ID : GALLERY_DB_ID;
519 }
520
521 SetDirectory(parentId);
522 m_parentId = parentId;
523
524 // No SG & no devices uses special 'empty' screen
525 if (!parent || (parentId == GALLERY_DB_ID && count == 1))
526 {
527 parent.clear();
528 return false;
529 }
530
531 // Populate all subdirs
532 for (const ImagePtr & im : std::as_const(dirs))
533 {
534 if (im)
535 // Load sufficient thumbs from each dir as subsequent dirs may be empty
537 }
538
539 // Populate parent
541 PopulateThumbs(*parent, kMaxFolderThumbnails, files, dirs);
542
543 // Dirs shown before images
544 ImageList images = dirs + files;
545
546 // Validate marked images
547 if (!m_marked.isEmpty())
548 {
549 QSet<int> ids;
550 for (const QSharedPointer<ImageItem> & im : std::as_const(images))
551 ids.insert(im->m_id);
552 m_marked.intersect(ids);
553 }
554
555 // Parent is always first (for navigating up).
556 images.prepend(parent);
557
558 // Preserve current selection before view is destroyed
559 ImagePtrK selected = GetSelected();
560 int activeId = selected ? selected->m_id : 0;
561
562 // Construct view
563 Populate(images);
564
565 // Reinstate selection, falling back to parent
566 Select(activeId);
567
568 return true;
569}
570
571
578void DirectoryView::LoadDirThumbs(ImageItem &parent, int thumbsNeeded, int level)
579{
580 // Use cached data, if available
581 if (PopulateFromCache(parent, thumbsNeeded))
582 return;
583
584 // Load child images & dirs
585 ImageList files;
586 ImageList dirs;
587 m_mgr.GetChildren(parent.m_id, files, dirs);
588
589 PopulateThumbs(parent, thumbsNeeded, files, dirs, level);
590}
591
592
603void DirectoryView::PopulateThumbs(ImageItem &parent, int thumbsNeeded,
604 const ImageList &files, const ImageList &dirs,
605 int level)
606{
607 // Set parent stats
608 parent.m_fileCount = files.size();
609 parent.m_dirCount = dirs.size();
610
611 // Locate user assigned thumb amongst children, if defined
612 ImagePtr userIm;
613 if (parent.m_userThumbnail != 0)
614 {
615 ImageList images = files + dirs;
616 // ImageItem has been explicitly marked Q_DISABLE_COPY
617 for (const ImagePtr & im : std::as_const(images))
618 {
619 if (im && im->m_id == parent.m_userThumbnail)
620 { // cppcheck-suppress useStlAlgorithm
621 userIm = im;
622 break;
623 }
624 }
625 }
626
627 // Children to use as thumbnails
628 ImageList thumbFiles;
629 ImageList thumbDirs;
630
631 if (!userIm)
632 {
633 // Construct multi-thumbnail from all children
634 thumbFiles = files;
635 thumbDirs = dirs;
636 }
637 else if (userIm->IsFile())
638 {
639 thumbFiles.append(userIm);
640 thumbsNeeded = 1;
641 }
642 else
643 {
644 thumbDirs.append(userIm);
645 }
646
647 // Fill parent thumbs from child files first
648 // Whilst they're available fill as many as possible for cache
649#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
650 for (int i = 0; i < std::min(kMaxFolderThumbnails, thumbFiles.size()); ++i)
651#else
652 for (int i = 0; i < std::min(kMaxFolderThumbnails, static_cast<int>(thumbFiles.size())); ++i)
653#endif
654 {
655 parent.m_thumbNails.append(thumbFiles.at(i)->m_thumbNails.at(0));
656 --thumbsNeeded;
657 }
658
659 // Only recurse if necessary
660 if (thumbsNeeded > 0)
661 {
662 // Prevent lengthy/infinite recursion due to deep/cyclic folder
663 // structures
664 if (++level > 10)
665 {
666 LOG(VB_GENERAL, LOG_NOTICE, LOC +
667 "Directory thumbnails are more than 10 levels deep");
668 }
669 else
670 {
671 // Recursively load subdir thumbs to try to get 1 thumb from each
672 for (const ImagePtr & im : std::as_const(thumbDirs))
673 {
674 if (!im)
675 continue;
676
677 // Load sufficient thumbs from each dir as subsequent dirs may
678 // be empty
679 LoadDirThumbs(*im, thumbsNeeded, level);
680
681 if (!im->m_thumbNails.empty())
682 {
683 // Add first thumbnail to parent thumb
684 parent.m_thumbNails.append(im->m_thumbNails.at(0));
685
686 // Quit when we have sufficient thumbs
687 if (--thumbsNeeded == 0)
688 break;
689 }
690 }
691
692 // If insufficient dirs to supply 1 thumb per dir, use other dir
693 // thumbs (indices 1-3) as well
694 int i = 0;
695 while (thumbsNeeded > 0 && ++i < kMaxFolderThumbnails)
696 {
697 for (const QSharedPointer<ImageItem> & im : std::as_const(thumbDirs))
698 {
699 if (i < im->m_thumbNails.size())
700 {
701 parent.m_thumbNails.append(im->m_thumbNails.at(i));
702 if (--thumbsNeeded == 0)
703 break;
704 }
705 }
706 }
707 }
708 }
709
710 // Flag the cached entry with number of thumbs loaded. If future uses require
711 // more, then the dir must be reloaded.
712 // For user thumbs and dirs with insufficient child images, the cache is always valid
713 int scanned = (userIm || thumbsNeeded > 0)
715 : parent.m_thumbNails.size();
716
717 // Cache result to optimize navigation
718 Cache(parent, scanned);
719}
720
721
726void DirectoryView::Clear(bool /*resetParent*/)
727{
728 ClearMarked();
729 ClearCache();
731}
732
733
738{
739 // Any marking clears previous marks
742}
743
744
750void DirectoryView::Mark(int id, bool mark)
751{
752 if (mark)
753 {
754 // Any marking clears previous marks
756 m_marked.Add(id);
757 }
758 else
759 {
760 m_prevMarked.remove(id);
761 m_marked.remove(id);
762 }
763}
764
765
770{
771 // Any marking clears previous marks
774}
775
776
781{
782 m_marked.Clear();
784}
785
786
792{
793 if (m_marked.IsFor(newParent))
794 // Directory hasn't changed
795 return;
796
797 // Markings are cleared on every dir change
798 // Any current markings become previous markings
799 // Only 1 set of previous markings are preserved
800 if (m_prevMarked.IsFor(newParent))
801 {
802 // Returned to dir of previous markings: reinstate them
805 return;
806 }
807
808 if (!m_marked.isEmpty())
809 // Preserve current markings
811
812 // Initialise current markings for new dir
813 m_marked.Initialise(newParent);
814}
815
816
822{
823 // hiddenMarked is true if 1 or more marked items are hidden
824 // unhiddenMarked is true if 1 or more marked items are not hidden
825 bool hiddenMarked = false;
826 bool unhiddenMarked = false;
827 for (int id : std::as_const(m_marked))
828 {
829 ImagePtrK im = m_images.value(id);
830 if (!im)
831 continue;
832
833 if (im->m_isHidden)
834 hiddenMarked = true;
835 else
836 unhiddenMarked = true;
837
838 if (hiddenMarked && unhiddenMarked)
839 break;
840 }
841
842 return {GetSelected(), m_sequence.size() - 1,
844 hiddenMarked, unhiddenMarked};
845}
846
847
855{
856 DirCacheEntry cached(m_dirCache.value(dir.m_id));
857 if (cached.m_dirCount == -1 || cached.m_thumbCount < required)
858 return false;
859
860 dir.m_fileCount = cached.m_fileCount;
861 dir.m_dirCount = cached.m_dirCount;
862 dir.m_thumbNails = cached.m_thumbs;
863
864 LOG(VB_FILE, LOG_DEBUG, LOC + "Using cached " + cached.ToString(dir.m_id));
865 return true;
866}
867
868
874void DirectoryView::Cache(ImageItemK &dir, int thumbCount)
875{
876 // Cache counts & thumbnails for each dir so that we don't need to reload its
877 // children from Db each time it's displayed
878 DirCacheEntry cacheEntry(dir.m_parentId, dir.m_dirCount, dir.m_fileCount,
879 dir.m_thumbNails, thumbCount);
880
881 m_dirCache.insert(dir.m_id, cacheEntry);
882
883 // Cache images used by dir thumbnails
884 for (const ThumbPair & thumb : std::as_const(dir.m_thumbNails))
885 {
886 // Do not overwrite any existing image url nor parent.
887 // Image url is cached when image is displayed as a child, but not as a
888 // ancestor dir thumbnail
889 // First cache attempt will be by parent. Subsequent attempts may be
890 // by ancestor dirs.
891 if (!m_fileCache.contains(thumb.first))
892 FlatView::Cache(thumb.first, dir.m_id, "", thumb.second);
893 }
894 LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cacheEntry.ToString(dir.m_id));
895}
896
897
902{
903 LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared Dir cache");
904 m_dirCache.clear();
906}
907
908
916QStringList DirectoryView::RemoveImage(int id, bool deleted)
917{
918 QStringList urls;
919 int dirId = id;
920
921 if (deleted)
922 {
923 m_marked.remove(id);
924 m_prevMarked.remove(id);
925 }
926
927 // If id is a file then start with its parent
928 if (m_fileCache.contains(id))
929 {
930 // Clear file cache & start from its parent dir
931 dirId = m_fileCache.value(id).m_parent;
932 urls = FlatView::ClearImage(id, deleted);
933 }
934
935 // Clear ancestor dirs
936 while (m_dirCache.contains(dirId))
937 {
938 LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from dir cache").arg(dirId));
939 DirCacheEntry dir = m_dirCache.take(dirId);
940 dirId = dir.m_parent;
941 }
942 return urls;
943}
944
945
953bool TreeView::LoadFromDb(int parentId)
954{
955 m_parentId = parentId;
956
957 // Load visible subtree of the parent
958 // Ordered images of parent first, then breadth-first recursion of ordered dirs
959 ImageList files;
961
962 // Load view
963 Populate(files);
964
965 return !files.isEmpty();
966}
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