MythTV  master
galleryviews.cpp
Go to the documentation of this file.
1 #include "galleryviews.h"
2 
3 #include <cmath> // for qsrand
4 #include <random>
5 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
6 #include <QRandomGenerator>
7 #endif
8 
9 #define LOC QString("Galleryviews: ")
10 
12 const static int kMaxFolderThumbnails = 4;
13 
20 const double LEADING_BETA_SHAPE = 0.175;
22 const double TRAILING_BETA_SHAPE = 0.31;
23 
25 const double DEFAULT_WEIGHT = std::pow(0.5, TRAILING_BETA_SHAPE - 1) *
26  std::pow(0.5, LEADING_BETA_SHAPE - 1);
28 const qint64 BETA_CLIP = 60 * 60 * 24;
29 
30 
36 {
37  ImageListK files;
38  foreach (int id, m_sequence)
39  files.append(m_images.value(id));
40  return files;
41 }
42 
43 
49 {
50  return m_active < 0 || m_active >= m_sequence.size()
51  ? ImagePtrK() : m_images.value(m_sequence.at(m_active));
52 }
53 
54 
59 QString FlatView::GetPosition() const
60 {
61  return QString("%1/%2").arg(m_active + 1).arg(m_sequence.size());
62 }
63 
64 
70 bool FlatView::Update(int id)
71 {
72  ImagePtrK im = m_images.value(id);
73  if (!im)
74  return false;
75 
76  // Get updated image
77  ImageList files;
78  ImageList dirs;
79  ImageIdList ids = ImageIdList() << id;
80  if (m_mgr.GetImages(ids, files, dirs) != 1 || files.size() != 1)
81  return false;
82 
83  bool active = (im == GetSelected());
84 
85  // Replace image
86  m_images.insert(id, files.at(0));
87 
88  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Modified id %1").arg(id));
89 
90  return active;
91 }
92 
93 
101 bool FlatView::Select(int id, int fallback)
102 {
103  // Select first appearance of image
104  int index = m_sequence.indexOf(id);
105  if (index >= 0)
106  {
107  m_active = index;
108  return true;
109  }
110 
111  if (fallback >= 0)
112  m_active = fallback;
113 
114  return false;
115 }
116 
117 
122 void FlatView::Clear(bool resetParent)
123 {
124  m_images.clear();
125  m_sequence.clear();
126  m_active = -1;
127  if (resetParent)
129 }
130 
131 
137 {
138  return m_sequence.isEmpty() || m_active + inc >= m_sequence.size()
139  ? ImagePtrK() : m_images.value(m_sequence.at(m_active + inc));
140 }
141 
142 
149 {
150  if (m_sequence.isEmpty())
151  return ImagePtrK();
152 
153  // Preserve index as it may be reset when wrapping
154  int next = m_active + inc;
155 
156  // Regenerate unordered views when wrapping
157  if (next >= m_sequence.size() && m_order != kOrdered && !LoadFromDb(m_parentId))
158  // Images have disappeared
159  return ImagePtrK();
160 
161  m_active = next % m_sequence.size();
162  return m_images.value(m_sequence.at(m_active));
163 }
164 
165 
171 {
172  return m_sequence.isEmpty() || m_active < inc
173  ? ImagePtrK() : m_images.value(m_sequence.at(m_active - inc));
174 }
175 
176 
182 {
183  if (m_sequence.isEmpty())
184  return ImagePtrK();
185 
186  // Wrap avoiding modulo of negative uncertainty
187  m_active -= inc % m_sequence.size();
188  if (m_active < 0)
189  m_active += m_sequence.size();
190 
191  return m_images.value(m_sequence.at(m_active));
192 }
193 
194 
200 {
201  // Do not reset parent
202  Clear(false);
203 
204  if (files.isEmpty())
205  return;
206 
207  foreach (ImagePtrK im, files)
208  {
209  // Add image to view
210  m_images.insert(im->m_id, im);
211 
212  // Cache all displayed images
213  if (im->IsFile())
214  Cache(im->m_id, im->m_parentId, im->m_url, im->m_thumbNails.at(0).second);
215  }
216 
217  if (files.size() == 1 || m_order == kOrdered || m_order == kShuffle)
218  {
219  // Default sequence is ordered
220  foreach (ImagePtrK im, files)
221  m_sequence.append(im->m_id);
222  }
223 
224  if (files.size() > 1)
225  {
226  // Modify viewing sequence
227  if (m_order == kShuffle)
228  {
229  std::shuffle(m_sequence.begin(), m_sequence.end(),
230  std::mt19937(std::random_device()()));
231  }
232  else if (m_order == kRandom)
233  {
234 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
235  QVector<quint32> rands;
236  rands.resize(files.size());
237  QRandomGenerator::global()->fillRange(rands.data(), rands.size());
238 #else
239  qsrand(QTime::currentTime().msec());
240 #endif
241  // An image is not a valid candidate for its successor
242  int range = files.size() - 1;
243  int index = range;
244  for (int count = 0; count < files.size(); ++count)
245  {
246 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
247  int rand = rands[count] % range;
248 #else
249  int rand = qrand() % range;
250 #endif
251  // Avoid consecutive repeats
252  index = (rand < index) ? rand : rand + 1;
253  m_sequence.append(files.at(index)->m_id);
254  }
255  }
256  else if (m_order == kSeasonal)
257  {
258  WeightList weights = CalculateSeasonalWeights(files);
259  double maxWeight = weights.last();
260 
261 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
262  auto randgen = QRandomGenerator::global();
263 #else
264  qsrand(QTime::currentTime().msec());
265 #endif
266  for (int count = 0; count < files.size(); ++count)
267  {
268 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
269  // generateDouble() returns in the range [0, 1)
270  double randWeight = randgen->generateDouble() * maxWeight;
271 #else
272  double randWeight = qrand() * maxWeight / RAND_MAX;
273 #endif
274  WeightList::iterator it =
275  std::upper_bound(weights.begin(), weights.end(), randWeight);
276  int index = std::distance(weights.begin(), it);
277  m_sequence.append(files.at(index)->m_id);
278  }
279  }
280  }
281 }
282 
283 
295 {
296  WeightList weights(files.size());
297  double totalWeight = 0;
298  QDateTime now = QDateTime::currentDateTime();
299 
300  for (int i = 0; i < files.size(); ++i)
301  {
302  ImagePtrK im = files.at(i);
303  double weight = 0;
304 
305  if (im->m_date == 0)
306  weight = DEFAULT_WEIGHT;
307  else
308  {
309 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
310  QDateTime timestamp = QDateTime::fromTime_t(im->m_date);
311 #else
312  QDateTime timestamp = QDateTime::fromSecsSinceEpoch(im->m_date);
313 #endif
314  QDateTime curYearAnniversary =
315  QDateTime(QDate(now.date().year(),
316  timestamp.date().month(),
317  timestamp.date().day()),
318  timestamp.time());
319 
320  bool isAnniversaryPast = curYearAnniversary < now;
321 
322  QDateTime adjacentYearAnniversary =
323  QDateTime(QDate(now.date().year() +
324  (isAnniversaryPast ? 1 : -1),
325  timestamp.date().month(),
326  timestamp.date().day()),
327  timestamp.time());
328 
329  double range = llabs(curYearAnniversary.secsTo(
330  adjacentYearAnniversary)) + BETA_CLIP;
331 
332  // This calculation is not normalized, because that would require the
333  // beta function, which isn't part of the C++98 libraries. Weights
334  // that aren't normalized work just as well relative to each other.
335  QDateTime d1(isAnniversaryPast ? curYearAnniversary
336  : adjacentYearAnniversary);
337  QDateTime d2(isAnniversaryPast ? adjacentYearAnniversary
338  : curYearAnniversary);
339  weight = std::pow(llabs(now.secsTo(d1) + BETA_CLIP) / range,
341  * std::pow(llabs(now.secsTo(d2) + BETA_CLIP) / range,
342  LEADING_BETA_SHAPE - 1);
343  }
344  totalWeight += weight;
345  weights[i] = totalWeight;
346  }
347  return weights;
348 }
349 
350 
357 bool FlatView::LoadFromDb(int parentId)
358 {
359  m_parentId = parentId;
360 
361  // Load child images of the parent
362  ImageList files;
363  ImageList dirs;
364  m_mgr.GetChildren(m_parentId, files, dirs);
365 
366  // Load gallery datastore with current dir
367  Populate(files);
368 
369  return !files.isEmpty();
370 }
371 
372 
377 {
378  LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared File cache");
379  m_fileCache.clear();
380 }
381 
382 
389 QStringList FlatView::ClearImage(int id, bool remove)
390 {
391  if (remove)
392  {
393  m_sequence.removeAll(id);
394  m_images.remove(id);
395  }
396 
397  QStringList urls;
398  FileCacheEntry file = m_fileCache.take(id);
399 
400  if (!file.m_url.isEmpty())
401  urls << file.m_url;
402 
403  if (!file.m_thumbUrl.isEmpty())
404  urls << file.m_thumbUrl;
405 
406  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from file cache (%2)")
407  .arg(id).arg(urls.join(",")));
408  return urls;
409 }
410 
411 
416 void FlatView::Rotate(int id)
417 {
418  // Rotate sequence so that (first appearance of) specified image is
419  // at offset from front
420  int index = m_sequence.indexOf(id);
421  if (index >= 0)
422  {
423  int first = index % m_sequence.size();
424  if (first > 0)
425  m_sequence = m_sequence.mid(first) + m_sequence.mid(0, first);
426  }
427 }
428 
429 
437 void FlatView::Cache(int id, int parent, const QString &url, const QString &thumb)
438 {
439  // Cache parent dir so that dir thumbs are updated when a child changes.
440  // Also store urls for image cache cleanup
441  FileCacheEntry cached(parent, url, thumb);
442  m_fileCache.insert(id, cached);
443  LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cached.ToString(id));
444 }
445 
446 
447 QString DirCacheEntry::ToString(int id) const
448 {
449  QStringList ids;
450  foreach (const auto & thumb, m_thumbs)
451  ids << QString::number(thumb.first);
452  return QString("Dir %1 (%2, %3) Thumbs %4 (%5) Parent %6")
453  .arg(id).arg(m_fileCount).arg(m_dirCount).arg(ids.join(","))
454  .arg(m_thumbCount).arg(m_parent);
455 }
456 
457 
463  : FlatView(order)
464 {
465  m_marked.Clear();
467 }
468 
469 
475 {
476  return QString("%1/%2").arg(m_active).arg(m_sequence.size() - 1);
477 }
478 
479 
488 bool DirectoryView::LoadFromDb(int parentId)
489 {
490  // Determine parent (defaulting to ancestor) & get initial children
491  ImageList files;
492  ImageList dirs;
493  ImagePtr parent;
494  int count = 0;
495  // Root is guaranteed to return at least 1 item
496  while ((count = m_mgr.GetDirectory(parentId, parent, files, dirs)) == 0)
497  {
498  // Fallback if dir no longer exists
499  // Ascend to Gallery for gallery subdirs, Root for device dirs & Gallery
500  parentId = parentId > PHOTO_DB_ID ? PHOTO_DB_ID : GALLERY_DB_ID;
501  }
502 
503  SetDirectory(parentId);
504  m_parentId = parentId;
505 
506  // No SG & no devices uses special 'empty' screen
507  if (!parent || (parentId == GALLERY_DB_ID && count == 1))
508  {
509  parent.clear();
510  return false;
511  }
512 
513  // Populate all subdirs
514  foreach (ImagePtr im, dirs)
515  {
516  if (im)
517  // Load sufficient thumbs from each dir as subsequent dirs may be empty
519  }
520 
521  // Populate parent
523  PopulateThumbs(*parent, kMaxFolderThumbnails, files, dirs);
524 
525  // Dirs shown before images
526  ImageList images = dirs + files;
527 
528  // Validate marked images
529  if (!m_marked.isEmpty())
530  {
531  QSet<int> ids;
532  foreach (ImagePtrK im, images)
533  ids.insert(im->m_id);
534  m_marked.intersect(ids);
535  }
536 
537  // Parent is always first (for navigating up).
538  images.prepend(parent);
539 
540  // Preserve current selection before view is destroyed
541  ImagePtrK selected = GetSelected();
542  int activeId = selected ? selected->m_id : 0;
543 
544  // Construct view
545  Populate(images);
546 
547  // Reinstate selection, falling back to parent
548  Select(activeId);
549 
550  return true;
551 }
552 
553 
560 void DirectoryView::LoadDirThumbs(ImageItem &parent, int thumbsNeeded, int level)
561 {
562  // Use cached data, if available
563  if (PopulateFromCache(parent, thumbsNeeded))
564  return;
565 
566  // Load child images & dirs
567  ImageList files;
568  ImageList dirs;
569  m_mgr.GetChildren(parent.m_id, files, dirs);
570 
571  PopulateThumbs(parent, thumbsNeeded, files, dirs, level);
572 }
573 
574 
585 void DirectoryView::PopulateThumbs(ImageItem &parent, int thumbsNeeded,
586  const ImageList &files, const ImageList &dirs,
587  int level)
588 {
589  // Set parent stats
590  parent.m_fileCount = files.size();
591  parent.m_dirCount = dirs.size();
592 
593  // Locate user assigned thumb amongst children, if defined
594  ImagePtr userIm;
595  if (parent.m_userThumbnail != 0)
596  {
597  foreach (ImagePtr im, files + dirs)
598  {
599  if (im && im->m_id == parent.m_userThumbnail)
600  {
601  userIm = im;
602  break;
603  }
604  }
605  }
606 
607  // Children to use as thumbnails
608  ImageList thumbFiles;
609  ImageList thumbDirs;
610 
611  if (!userIm)
612  {
613  // Construct multi-thumbnail from all children
614  thumbFiles = files;
615  thumbDirs = dirs;
616  }
617  else if (userIm->IsFile())
618  {
619  thumbFiles.append(userIm);
620  thumbsNeeded = 1;
621  }
622  else
623  thumbDirs.append(userIm);
624 
625  // Fill parent thumbs from child files first
626  // Whilst they're available fill as many as possible for cache
627  for (int i = 0; i < qMin(kMaxFolderThumbnails, thumbFiles.size()); ++i)
628  {
629  parent.m_thumbNails.append(thumbFiles.at(i)->m_thumbNails.at(0));
630  --thumbsNeeded;
631  }
632 
633  // Only recurse if necessary
634  if (thumbsNeeded > 0)
635  {
636  // Prevent lengthy/infinite recursion due to deep/cyclic folder
637  // structures
638  if (++level > 10)
639  {
640  LOG(VB_GENERAL, LOG_NOTICE, LOC +
641  "Directory thumbnails are more than 10 levels deep");
642  }
643  else
644  {
645  // Recursively load subdir thumbs to try to get 1 thumb from each
646  foreach (ImagePtr im, thumbDirs)
647  {
648  if (!im)
649  continue;
650 
651  // Load sufficient thumbs from each dir as subsequent dirs may
652  // be empty
653  LoadDirThumbs(*im, thumbsNeeded, level);
654 
655  if (!im->m_thumbNails.empty())
656  {
657  // Add first thumbnail to parent thumb
658  parent.m_thumbNails.append(im->m_thumbNails.at(0));
659 
660  // Quit when we have sufficient thumbs
661  if (--thumbsNeeded == 0)
662  break;
663  }
664  }
665 
666  // If insufficient dirs to supply 1 thumb per dir, use other dir
667  // thumbs (indices 1-3) as well
668  int i = 0;
669  while (thumbsNeeded > 0 && ++i < kMaxFolderThumbnails)
670  {
671  foreach (ImagePtrK im, thumbDirs)
672  {
673  if (i < im->m_thumbNails.size())
674  {
675  parent.m_thumbNails.append(im->m_thumbNails.at(i));
676  if (--thumbsNeeded == 0)
677  break;
678  }
679  }
680  }
681  }
682  }
683 
684  // Flag the cached entry with number of thumbs loaded. If future uses require
685  // more, then the dir must be reloaded.
686  // For user thumbs and dirs with insufficient child images, the cache is always valid
687  int scanned = (userIm || thumbsNeeded > 0)
689  : parent.m_thumbNails.size();
690 
691  // Cache result to optimize navigation
692  Cache(parent, scanned);
693 }
694 
695 
700 void DirectoryView::Clear(bool /*resetParent*/)
701 {
702  ClearMarked();
703  ClearCache();
704  FlatView::Clear();
705 }
706 
707 
712 {
713  // Any marking clears previous marks
716 }
717 
718 
724 void DirectoryView::Mark(int id, bool mark)
725 {
726  if (mark)
727  {
728  // Any marking clears previous marks
730  m_marked.Add(id);
731  }
732  else
733  {
734  m_prevMarked.remove(id);
735  m_marked.remove(id);
736  }
737 }
738 
739 
744 {
745  // Any marking clears previous marks
748 }
749 
750 
755 {
756  m_marked.Clear();
758 }
759 
760 
765 void DirectoryView::SetDirectory(int newParent)
766 {
767  if (m_marked.IsFor(newParent))
768  // Directory hasn't changed
769  return;
770 
771  // Markings are cleared on every dir change
772  // Any current markings become previous markings
773  // Only 1 set of previous markings are preserved
774  if (m_prevMarked.IsFor(newParent))
775  {
776  // Returned to dir of previous markings: reinstate them
779  return;
780  }
781 
782  if (!m_marked.isEmpty())
783  // Preserve current markings
785 
786  // Initialise current markings for new dir
787  m_marked.Initialise(newParent);
788 }
789 
790 
796 {
797  // hiddenMarked is true if 1 or more marked items are hidden
798  // unhiddenMarked is true if 1 or more marked items are not hidden
799  bool hiddenMarked = false;
800  bool unhiddenMarked = false;
801  foreach (int id, m_marked)
802  {
803  ImagePtrK im = m_images.value(id);
804  if (!im)
805  continue;
806 
807  if (im->m_isHidden)
808  hiddenMarked = true;
809  else
810  unhiddenMarked = true;
811 
812  if (hiddenMarked && unhiddenMarked)
813  break;
814  }
815 
816  return MenuSubjects(GetSelected(), m_sequence.size() - 1,
818  hiddenMarked, unhiddenMarked);
819 }
820 
821 
829 {
830  DirCacheEntry cached(m_dirCache.value(dir.m_id));
831  if (cached.m_dirCount == -1 || cached.m_thumbCount < required)
832  return false;
833 
834  dir.m_fileCount = cached.m_fileCount;
835  dir.m_dirCount = cached.m_dirCount;
836  dir.m_thumbNails = cached.m_thumbs;
837 
838  LOG(VB_FILE, LOG_DEBUG, LOC + "Using cached " + cached.ToString(dir.m_id));
839  return true;
840 }
841 
842 
848 void DirectoryView::Cache(ImageItemK &dir, int thumbCount)
849 {
850  // Cache counts & thumbnails for each dir so that we don't need to reload its
851  // children from Db each time it's displayed
852  DirCacheEntry cacheEntry(dir.m_parentId, dir.m_dirCount, dir.m_fileCount,
853  dir.m_thumbNails, thumbCount);
854 
855  m_dirCache.insert(dir.m_id, cacheEntry);
856 
857  // Cache images used by dir thumbnails
858  foreach (const ThumbPair &thumb, dir.m_thumbNails)
859  {
860  // Do not overwrite any existing image url nor parent.
861  // Image url is cached when image is displayed as a child, but not as a
862  // ancestor dir thumbnail
863  // First cache attempt will be by parent. Subsequent attempts may be
864  // by ancestor dirs.
865  if (!m_fileCache.contains(thumb.first))
866  FlatView::Cache(thumb.first, dir.m_id, "", thumb.second);
867  }
868  LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cacheEntry.ToString(dir.m_id));
869 }
870 
871 
876 {
877  LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared Dir cache");
878  m_dirCache.clear();
880 }
881 
882 
890 QStringList DirectoryView::RemoveImage(int id, bool deleted)
891 {
892  QStringList urls;
893  int dirId = id;
894 
895  if (deleted)
896  {
897  m_marked.remove(id);
898  m_prevMarked.remove(id);
899  }
900 
901  // If id is a file then start with its parent
902  if (m_fileCache.contains(id))
903  {
904  // Clear file cache & start from its parent dir
905  dirId = m_fileCache.value(id).m_parent;
906  urls = FlatView::ClearImage(id, deleted);
907  }
908 
909  // Clear ancestor dirs
910  while (m_dirCache.contains(dirId))
911  {
912  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from dir cache").arg(dirId));
913  DirCacheEntry dir = m_dirCache.take(dirId);
914  dirId = dir.m_parent;
915  }
916  return urls;
917 }
918 
919 
927 bool TreeView::LoadFromDb(int parentId)
928 {
929  m_parentId = parentId;
930 
931  // Load visible subtree of the parent
932  // Ordered images of parent first, then breadth-first recursion of ordered dirs
933  ImageList files;
934  m_mgr.GetImageTree(m_parentId, files);
935 
936  // Load view
937  Populate(files);
938 
939  return !files.isEmpty();
940 }
QPair< int, QString > ThumbPair
Definition: imagetypes.h:63
QSharedPointer< ImageItem > ImagePtr
Definition: imagetypes.h:166
DirectoryView(SlideOrderType order)
Constructs a view of images & directories that can be marked.
void Invert(const ImageIdList &all)
Definition: galleryviews.h:43
const qint64 BETA_CLIP
The edges of the distribution get clipped to avoid a singularity.
void Cache(int id, int parent, const QString &url, const QString &thumb)
Cache image properties to optimize UI.
ImageIdList m_sequence
The sequence in which to display images.
Definition: galleryviews.h:134
QList< ThumbPair > m_thumbNails
Definition: imagetypes.h:118
A datastore of images for display by a screen.
Definition: galleryviews.h:98
QHash< int, FileCacheEntry > m_fileCache
Caches displayed image files.
Definition: galleryviews.h:138
bool Select(int id, int fallback=0)
Selects first occurrence of an image.
Each image appears exactly once, but in random order.
Definition: galleryviews.h:23
void ClearCache()
Clears UI cache.
QString GetPosition() const
Get positional status.
Provides view datastores for Gallery screens.
bool IsFor(int id)
Definition: galleryviews.h:40
QString ToString(int id) const
const double DEFAULT_WEIGHT
Photos without an exif timestamp will default to the mode of the beta distribution.
QStringList ClearImage(int id, bool remove=false)
Clear file from UI cache and optionally from view.
QVector< double > WeightList
Seasonal weightings for images in a view.
Definition: galleryviews.h:30
void Add(const ImageIdList &newIds)
Definition: galleryviews.h:41
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,...
bool LoadFromDb(int parentId) override
Populate view from database as images/subdirs of a directory. View is ordered: Parent dir,...
int m_fileCount
Number of child images (dirs only)
Definition: imagetypes.h:120
int m_parentId
Id of parent dir.
Definition: imagetypes.h:95
void Initialise(int id)
Definition: galleryviews.h:38
static const int kMaxFolderThumbnails
Number of thumbnails to use for folders.
ImagePtrK HasPrev(int inc) const
Peeks at previous image in view but does not decrement iterator.
void Cache(ImageItemK &dir, int thumbCount)
Cache displayed dir.
Definition: lang.c:20
bool Update(int id)
Updates view with images that have been updated.
const double LEADING_BETA_SHAPE
Tuning parameter for seasonal weights, between 0 and 1, where lower numbers give greater weight to se...
MarkedFiles m_prevMarked
Marked items in previous dir.
Definition: galleryviews.h:202
const double TRAILING_BETA_SHAPE
See LEADING_BETA_SHAPE.
void Clear(bool resetParent=true)
Reset view.
ImageListK GetAllNodes() const
Get all images/dirs in view.
Biased random selection so that images are more likely to appear on anniversaries.
Definition: galleryviews.h:25
int GetChildren(int id, ImageList &files, ImageList &dirs) const
Return (local or remote) images that are direct children of a dir.
Random selection from view. An image may be absent or appear multiple times.
Definition: galleryviews.h:24
bool PopulateFromCache(ImageItem &dir, int required)
Retrieve cached dir, if available.
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:172
bool LoadFromDb(int parentId) override
Populate view from database as images of a directory sub-tree. Default order of a tree is depth-first...
SlideOrderType
Order of images in slideshow.
Definition: galleryviews.h:21
QString GetPosition() const
Get positional status.
void MarkAll()
Mark all images/dirs.
int m_userThumbnail
Id of thumbnail to use as cover (dirs only)
Definition: imagetypes.h:113
int GetDirectory(int id, ImagePtr &parent, ImageList &files, ImageList &dirs) const
Return images (local and/or remote) for a dir and its direct children.
#define LOC
Definition: galleryviews.cpp:9
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:88
void Populate(ImageList &files)
Fills view with Db images, re-ordering them as required.
void Clear()
Definition: galleryviews.h:39
QList< ThumbPair > m_thumbs
Definition: galleryviews.h:160
void Rotate(int id)
Rotate view so that starting image is at front.
QString ToString(int id)
Definition: galleryviews.h:84
ImagePtrK GetSelected() const
Get current selection.
void Clear(bool resetParent=true)
Resets view.
void ClearMarked()
Unmark all items.
int GetImages(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Returns images (local or remote but not a combination)
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:76
void GetImageTree(int id, ImageList &files) const
Return all files (local or remote) in the sub-trees of a dir.
void ClearCache()
Clears UI cache.
QList< ImagePtr > ImageList
Definition: imagetypes.h:167
void SetDirectory(int newParent)
Manage markings on tree navigation.
ImagePtrK Prev(int inc)
Decrements iterator and returns previous image. Wraps at start.
int m_dirCount
Id & URLs of thumbnail(s). 1 for a file, 4 for dirs.
Definition: imagetypes.h:119
int m_active
Sequence index of current selected image.
Definition: galleryviews.h:135
void LoadDirThumbs(ImageItem &parent, int thumbsNeeded, int level=0)
Populate thumbs for a dir.
QList< int > ImageIdList
Definition: imagetypes.h:59
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
PictureAttribute next(PictureAttributeSupported Supported, PictureAttribute Attribute)
Represents a picture, video or directory.
Definition: imagetypes.h:67
ImagePtrK Next(int inc)
Advance iterator and return next image, wrapping if necessary. Regenerates unordered views on wrap.
QStringList RemoveImage(int id, bool deleted=false)
Clear file/dir and all its ancestors from UI cache so that ancestor thumbnails are recalculated....
MenuSubjects GetMenuSubjects()
Determine current selection, markings & various info to support menu display.
int m_parentId
Definition: galleryviews.h:130
#define PHOTO_DB_ID
Definition: imagetypes.h:28
void InvertMarked()
Mark all unmarked items, unmark all marked items.
virtual bool LoadFromDb(int parentId)
Populate view with database images from a directory.
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...
MarkedFiles m_marked
Marked items in current dir/view.
Definition: galleryviews.h:201
Records dir info for every displayed dir.
Definition: galleryviews.h:145
ImageManagerFe & m_mgr
Definition: galleryviews.h:132
QHash< int, ImagePtrK > m_images
Image objects currently displayed.
Definition: galleryviews.h:133
int m_id
Uniquely identifies an image (file/dir).
Definition: imagetypes.h:88
#define GALLERY_DB_ID
Definition: imagetypes.h:26
SlideOrderType m_order
Definition: galleryviews.h:131
ImageIdList GetChildren() const
Definition: galleryviews.h:197
QHash< int, DirCacheEntry > m_dirCache
Caches displayed image dirs.
Definition: galleryviews.h:205
ImagePtrK HasNext(int inc) const
Peeks at next image in view but does not advance iterator.
Ordered as per user setting GallerySortOrder.
Definition: galleryviews.h:22
QList< ImagePtrK > ImageListK
Definition: imagetypes.h:173
A snapshot of current selection, markings & dir info when menu is invoked.
Definition: galleryviews.h:52