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, dirs;
78  ImageIdList ids = ImageIdList() << id;
79  if (m_mgr.GetImages(ids, files, dirs) != 1 || files.size() != 1)
80  return false;
81 
82  bool active = (im == GetSelected());
83 
84  // Replace image
85  m_images.insert(id, files.at(0));
86 
87  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Modified id %1").arg(id));
88 
89  return active;
90 }
91 
92 
100 bool FlatView::Select(int id, int fallback)
101 {
102  // Select first appearance of image
103  int index = m_sequence.indexOf(id);
104  if (index >= 0)
105  {
106  m_active = index;
107  return true;
108  }
109 
110  if (fallback >= 0)
111  m_active = fallback;
112 
113  return false;
114 }
115 
116 
121 void FlatView::Clear(bool resetParent)
122 {
123  m_images.clear();
124  m_sequence.clear();
125  m_active = -1;
126  if (resetParent)
128 }
129 
130 
136 {
137  return m_sequence.isEmpty() || m_active + inc >= m_sequence.size()
138  ? ImagePtrK() : m_images.value(m_sequence.at(m_active + inc));
139 }
140 
141 
148 {
149  if (m_sequence.isEmpty())
150  return ImagePtrK();
151 
152  // Preserve index as it may be reset when wrapping
153  int next = m_active + inc;
154 
155  // Regenerate unordered views when wrapping
156  if (next >= m_sequence.size() && m_order != kOrdered && !LoadFromDb(m_parentId))
157  // Images have disappeared
158  return ImagePtrK();
159 
160  m_active = next % m_sequence.size();
161  return m_images.value(m_sequence.at(m_active));
162 }
163 
164 
170 {
171  return m_sequence.isEmpty() || m_active < inc
172  ? ImagePtrK() : m_images.value(m_sequence.at(m_active - inc));
173 }
174 
175 
181 {
182  if (m_sequence.isEmpty())
183  return ImagePtrK();
184 
185  // Wrap avoiding modulo of negative uncertainty
186  m_active -= inc % m_sequence.size();
187  if (m_active < 0)
188  m_active += m_sequence.size();
189 
190  return m_images.value(m_sequence.at(m_active));
191 }
192 
193 
199 {
200  // Do not reset parent
201  Clear(false);
202 
203  if (files.isEmpty())
204  return;
205 
206  foreach (ImagePtrK im, files)
207  {
208  // Add image to view
209  m_images.insert(im->m_id, im);
210 
211  // Cache all displayed images
212  if (im->IsFile())
213  Cache(im->m_id, im->m_parentId, im->m_url, im->m_thumbNails.at(0).second);
214  }
215 
216  if (files.size() == 1 || m_order == kOrdered || m_order == kShuffle)
217  {
218  // Default sequence is ordered
219  foreach (ImagePtrK im, files)
220  m_sequence.append(im->m_id);
221  }
222 
223  if (files.size() > 1)
224  {
225  // Modify viewing sequence
226  if (m_order == kShuffle)
227  {
228  std::shuffle(m_sequence.begin(), m_sequence.end(),
229  std::mt19937(std::random_device()()));
230  }
231  else if (m_order == kRandom)
232  {
233 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
234  QVector<quint32> rands;
235  rands.resize(files.size());
236  QRandomGenerator::global()->fillRange(rands.data(), rands.size());
237 #else
238  qsrand(QTime::currentTime().msec());
239 #endif
240  // An image is not a valid candidate for its successor
241  int range = files.size() - 1;
242  int index = range;
243  for (int count = 0; count < files.size(); ++count)
244  {
245 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
246  int rand = rands[count] % range;
247 #else
248  int rand = qrand() % range;
249 #endif
250  // Avoid consecutive repeats
251  index = (rand < index) ? rand : rand + 1;
252  m_sequence.append(files.at(index)->m_id);
253  }
254  }
255  else if (m_order == kSeasonal)
256  {
257  WeightList weights = CalculateSeasonalWeights(files);
258  double maxWeight = weights.last();
259 
260 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
261  auto randgen = QRandomGenerator::global();
262 #else
263  qsrand(QTime::currentTime().msec());
264 #endif
265  for (int count = 0; count < files.size(); ++count)
266  {
267 #if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
268  // generateDouble() returns in the range [0, 1)
269  double randWeight = randgen->generateDouble() * maxWeight;
270 #else
271  double randWeight = qrand() * maxWeight / RAND_MAX;
272 #endif
273  WeightList::iterator it =
274  std::upper_bound(weights.begin(), weights.end(), randWeight);
275  int index = std::distance(weights.begin(), it);
276  m_sequence.append(files.at(index)->m_id);
277  }
278  }
279  }
280 }
281 
282 
294 {
295  WeightList weights(files.size());
296  double totalWeight = 0;
297  QDateTime now = QDateTime::currentDateTime();
298 
299  for (int i = 0; i < files.size(); ++i)
300  {
301  ImagePtrK im = files.at(i);
302  double weight;
303 
304  if (im->m_date == 0)
305  weight = DEFAULT_WEIGHT;
306  else
307  {
308 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
309  QDateTime timestamp = QDateTime::fromTime_t(im->m_date);
310 #else
311  QDateTime timestamp = QDateTime::fromSecsSinceEpoch(im->m_date);
312 #endif
313  QDateTime curYearAnniversary =
314  QDateTime(QDate(now.date().year(),
315  timestamp.date().month(),
316  timestamp.date().day()),
317  timestamp.time());
318 
319  bool isAnniversaryPast = curYearAnniversary < now;
320 
321  QDateTime adjacentYearAnniversary =
322  QDateTime(QDate(now.date().year() +
323  (isAnniversaryPast ? 1 : -1),
324  timestamp.date().month(),
325  timestamp.date().day()),
326  timestamp.time());
327 
328  double range = llabs(curYearAnniversary.secsTo(
329  adjacentYearAnniversary)) + BETA_CLIP;
330 
331  // This calculation is not normalized, because that would require the
332  // beta function, which isn't part of the C++98 libraries. Weights
333  // that aren't normalized work just as well relative to each other.
334  QDateTime d1(isAnniversaryPast ? curYearAnniversary
335  : adjacentYearAnniversary);
336  QDateTime d2(isAnniversaryPast ? adjacentYearAnniversary
337  : curYearAnniversary);
338  weight = std::pow(llabs(now.secsTo(d1) + BETA_CLIP) / range,
340  * std::pow(llabs(now.secsTo(d2) + BETA_CLIP) / range,
341  LEADING_BETA_SHAPE - 1);
342  }
343  totalWeight += weight;
344  weights[i] = totalWeight;
345  }
346  return weights;
347 }
348 
349 
356 bool FlatView::LoadFromDb(int parentId)
357 {
358  m_parentId = parentId;
359 
360  // Load child images of the parent
361  ImageList files, dirs;
362  m_mgr.GetChildren(m_parentId, files, dirs);
363 
364  // Load gallery datastore with current dir
365  Populate(files);
366 
367  return !files.isEmpty();
368 }
369 
370 
375 {
376  LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared File cache");
377  m_fileCache.clear();
378 }
379 
380 
387 QStringList FlatView::ClearImage(int id, bool remove)
388 {
389  if (remove)
390  {
391  m_sequence.removeAll(id);
392  m_images.remove(id);
393  }
394 
395  QStringList urls;
396  FileCacheEntry file = m_fileCache.take(id);
397 
398  if (!file.m_url.isEmpty())
399  urls << file.m_url;
400 
401  if (!file.m_thumbUrl.isEmpty())
402  urls << file.m_thumbUrl;
403 
404  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from file cache (%2)")
405  .arg(id).arg(urls.join(",")));
406  return urls;
407 }
408 
409 
414 void FlatView::Rotate(int id)
415 {
416  // Rotate sequence so that (first appearance of) specified image is
417  // at offset from front
418  int index = m_sequence.indexOf(id);
419  if (index >= 0)
420  {
421  int first = index % m_sequence.size();
422  if (first > 0)
423  m_sequence = m_sequence.mid(first) + m_sequence.mid(0, first);
424  }
425 }
426 
427 
435 void FlatView::Cache(int id, int parent, const QString &url, const QString &thumb)
436 {
437  // Cache parent dir so that dir thumbs are updated when a child changes.
438  // Also store urls for image cache cleanup
439  FileCacheEntry cached(parent, url, thumb);
440  m_fileCache.insert(id, cached);
441  LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cached.ToString(id));
442 }
443 
444 
445 QString DirCacheEntry::ToString(int id) const
446 {
447  QStringList ids;
448  for (int i = 0; i < m_thumbs.size(); ++i)
449  ids << QString::number(m_thumbs.at(i).first);
450  return QString("Dir %1 (%2, %3) Thumbs %4 (%5) Parent %6")
451  .arg(id).arg(m_fileCount).arg(m_dirCount).arg(ids.join(","))
452  .arg(m_thumbCount).arg(m_parent);
453 }
454 
455 
461  : FlatView(order)
462 {
463  m_marked.Clear();
465 }
466 
467 
473 {
474  return QString("%1/%2").arg(m_active).arg(m_sequence.size() - 1);
475 }
476 
477 
486 bool DirectoryView::LoadFromDb(int parentId)
487 {
488  // Determine parent (defaulting to ancestor) & get initial children
489  ImageList files, dirs;
490  ImagePtr parent;
491  int count;
492  // Root is guaranteed to return at least 1 item
493  while ((count = m_mgr.GetDirectory(parentId, parent, files, dirs)) == 0)
494  {
495  // Fallback if dir no longer exists
496  // Ascend to Gallery for gallery subdirs, Root for device dirs & Gallery
497  parentId = parentId > PHOTO_DB_ID ? PHOTO_DB_ID : GALLERY_DB_ID;
498  }
499 
500  SetDirectory(parentId);
501  m_parentId = parentId;
502 
503  // No SG & no devices uses special 'empty' screen
504  if (!parent || (parentId == GALLERY_DB_ID && count == 1))
505  {
506  parent.clear();
507  return false;
508  }
509 
510  // Populate all subdirs
511  foreach (ImagePtr im, dirs)
512  {
513  if (im)
514  // Load sufficient thumbs from each dir as subsequent dirs may be empty
516  }
517 
518  // Populate parent
520  PopulateThumbs(*parent, kMaxFolderThumbnails, files, dirs);
521 
522  // Dirs shown before images
523  ImageList images = dirs + files;
524 
525  // Validate marked images
526  if (!m_marked.isEmpty())
527  {
528  QSet<int> ids;
529  foreach (ImagePtrK im, images)
530  ids.insert(im->m_id);
531  m_marked.intersect(ids);
532  }
533 
534  // Parent is always first (for navigating up).
535  images.prepend(parent);
536 
537  // Preserve current selection before view is destroyed
538  ImagePtrK selected = GetSelected();
539  int activeId = selected ? selected->m_id : 0;
540 
541  // Construct view
542  Populate(images);
543 
544  // Reinstate selection, falling back to parent
545  Select(activeId);
546 
547  return true;
548 }
549 
550 
557 void DirectoryView::LoadDirThumbs(ImageItem &parent, int thumbsNeeded, int level)
558 {
559  // Use cached data, if available
560  if (PopulateFromCache(parent, thumbsNeeded))
561  return;
562 
563  // Load child images & dirs
564  ImageList files, dirs;
565  m_mgr.GetChildren(parent.m_id, files, dirs);
566 
567  PopulateThumbs(parent, thumbsNeeded, files, dirs, level);
568 }
569 
570 
581 void DirectoryView::PopulateThumbs(ImageItem &parent, int thumbsNeeded,
582  const ImageList &files, const ImageList &dirs,
583  int level)
584 {
585  // Set parent stats
586  parent.m_fileCount = files.size();
587  parent.m_dirCount = dirs.size();
588 
589  // Locate user assigned thumb amongst children, if defined
590  ImagePtr userIm;
591  if (parent.m_userThumbnail != 0)
592  {
593  foreach (ImagePtr im, files + dirs)
594  {
595  if (im && im->m_id == parent.m_userThumbnail)
596  {
597  userIm = im;
598  break;
599  }
600  }
601  }
602 
603  // Children to use as thumbnails
604  ImageList thumbFiles, thumbDirs;
605 
606  if (!userIm)
607  {
608  // Construct multi-thumbnail from all children
609  thumbFiles = files;
610  thumbDirs = dirs;
611  }
612  else if (userIm->IsFile())
613  {
614  thumbFiles.append(userIm);
615  thumbsNeeded = 1;
616  }
617  else
618  thumbDirs.append(userIm);
619 
620  // Fill parent thumbs from child files first
621  // Whilst they're available fill as many as possible for cache
622  for (int i = 0; i < qMin(kMaxFolderThumbnails, thumbFiles.size()); ++i)
623  {
624  parent.m_thumbNails.append(thumbFiles.at(i)->m_thumbNails.at(0));
625  --thumbsNeeded;
626  }
627 
628  // Only recurse if necessary
629  if (thumbsNeeded > 0)
630  {
631  // Prevent lengthy/infinite recursion due to deep/cyclic folder
632  // structures
633  if (++level > 10)
634  LOG(VB_GENERAL, LOG_NOTICE, LOC +
635  "Directory thumbnails are more than 10 levels deep");
636  else
637  {
638  // Recursively load subdir thumbs to try to get 1 thumb from each
639  foreach (ImagePtr im, thumbDirs)
640  {
641  if (!im)
642  continue;
643 
644  // Load sufficient thumbs from each dir as subsequent dirs may
645  // be empty
646  LoadDirThumbs(*im, thumbsNeeded, level);
647 
648  if (!im->m_thumbNails.empty())
649  {
650  // Add first thumbnail to parent thumb
651  parent.m_thumbNails.append(im->m_thumbNails.at(0));
652 
653  // Quit when we have sufficient thumbs
654  if (--thumbsNeeded == 0)
655  break;
656  }
657  }
658 
659  // If insufficient dirs to supply 1 thumb per dir, use other dir
660  // thumbs (indices 1-3) as well
661  int i = 0;
662  while (thumbsNeeded > 0 && ++i < kMaxFolderThumbnails)
663  {
664  foreach (ImagePtrK im, thumbDirs)
665  {
666  if (i < im->m_thumbNails.size())
667  {
668  parent.m_thumbNails.append(im->m_thumbNails.at(i));
669  if (--thumbsNeeded == 0)
670  break;
671  }
672  }
673  }
674  }
675  }
676 
677  // Flag the cached entry with number of thumbs loaded. If future uses require
678  // more, then the dir must be reloaded.
679  // For user thumbs and dirs with insufficient child images, the cache is always valid
680  int scanned = (userIm || thumbsNeeded > 0)
682  : parent.m_thumbNails.size();
683 
684  // Cache result to optimize navigation
685  Cache(parent, scanned);
686 }
687 
688 
693 void DirectoryView::Clear(bool /*resetParent*/)
694 {
695  ClearMarked();
696  ClearCache();
697  FlatView::Clear();
698 }
699 
700 
705 {
706  // Any marking clears previous marks
709 }
710 
711 
717 void DirectoryView::Mark(int id, bool mark)
718 {
719  if (mark)
720  {
721  // Any marking clears previous marks
723  m_marked.Add(id);
724  }
725  else
726  {
727  m_prevMarked.remove(id);
728  m_marked.remove(id);
729  }
730 }
731 
732 
737 {
738  // Any marking clears previous marks
741 }
742 
743 
748 {
749  m_marked.Clear();
751 }
752 
753 
758 void DirectoryView::SetDirectory(int newParent)
759 {
760  if (m_marked.IsFor(newParent))
761  // Directory hasn't changed
762  return;
763 
764  // Markings are cleared on every dir change
765  // Any current markings become previous markings
766  // Only 1 set of previous markings are preserved
767  if (m_prevMarked.IsFor(newParent))
768  {
769  // Returned to dir of previous markings: reinstate them
772  return;
773  }
774 
775  if (!m_marked.isEmpty())
776  // Preserve current markings
778 
779  // Initialise current markings for new dir
780  m_marked.Initialise(newParent);
781 }
782 
783 
789 {
790  // hiddenMarked is true if 1 or more marked items are hidden
791  // unhiddenMarked is true if 1 or more marked items are not hidden
792  bool hiddenMarked = false;
793  bool unhiddenMarked = false;
794  foreach (int id, m_marked)
795  {
796  ImagePtrK im = m_images.value(id);
797  if (!im)
798  continue;
799 
800  if (im->m_isHidden)
801  hiddenMarked = true;
802  else
803  unhiddenMarked = true;
804 
805  if (hiddenMarked && unhiddenMarked)
806  break;
807  }
808 
809  return MenuSubjects(GetSelected(), m_sequence.size() - 1,
811  hiddenMarked, unhiddenMarked);
812 }
813 
814 
822 {
823  DirCacheEntry cached(m_dirCache.value(dir.m_id));
824  if (cached.m_dirCount == -1 || cached.m_thumbCount < required)
825  return false;
826 
827  dir.m_fileCount = cached.m_fileCount;
828  dir.m_dirCount = cached.m_dirCount;
829  dir.m_thumbNails = cached.m_thumbs;
830 
831  LOG(VB_FILE, LOG_DEBUG, LOC + "Using cached " + cached.ToString(dir.m_id));
832  return true;
833 }
834 
835 
841 void DirectoryView::Cache(ImageItemK &dir, int thumbCount)
842 {
843  // Cache counts & thumbnails for each dir so that we don't need to reload its
844  // children from Db each time it's displayed
845  DirCacheEntry cacheEntry(dir.m_parentId, dir.m_dirCount, dir.m_fileCount,
846  dir.m_thumbNails, thumbCount);
847 
848  m_dirCache.insert(dir.m_id, cacheEntry);
849 
850  // Cache images used by dir thumbnails
851  foreach (const ThumbPair &thumb, dir.m_thumbNails)
852  {
853  // Do not overwrite any existing image url nor parent.
854  // Image url is cached when image is displayed as a child, but not as a
855  // ancestor dir thumbnail
856  // First cache attempt will be by parent. Subsequent attempts may be
857  // by ancestor dirs.
858  if (!m_fileCache.contains(thumb.first))
859  FlatView::Cache(thumb.first, dir.m_id, "", thumb.second);
860  }
861  LOG(VB_FILE, LOG_DEBUG, LOC + "Caching " + cacheEntry.ToString(dir.m_id));
862 }
863 
864 
869 {
870  LOG(VB_FILE, LOG_DEBUG, LOC + "Cleared Dir cache");
871  m_dirCache.clear();
873 }
874 
875 
883 QStringList DirectoryView::RemoveImage(int id, bool deleted)
884 {
885  QStringList urls;
886  int dirId = id;
887 
888  if (deleted)
889  {
890  m_marked.remove(id);
891  m_prevMarked.remove(id);
892  }
893 
894  // If id is a file then start with its parent
895  if (m_fileCache.contains(id))
896  {
897  // Clear file cache & start from its parent dir
898  dirId = m_fileCache.value(id).m_parent;
899  urls = FlatView::ClearImage(id, deleted);
900  }
901 
902  // Clear ancestor dirs
903  while (m_dirCache.contains(dirId))
904  {
905  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Cleared %1 from dir cache").arg(dirId));
906  DirCacheEntry dir = m_dirCache.take(dirId);
907  dirId = dir.m_parent;
908  }
909  return urls;
910 }
911 
912 
920 bool TreeView::LoadFromDb(int parentId)
921 {
922  m_parentId = parentId;
923 
924  // Load visible subtree of the parent
925  // Ordered images of parent first, then breadth-first recursion of ordered dirs
926  ImageList files;
927  m_mgr.GetImageTree(m_parentId, files);
928 
929  // Load view
930  Populate(files);
931 
932  return !files.isEmpty();
933 }
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:131
QList< ThumbPair > m_thumbNails
Definition: imagetypes.h:126
A datastore of images for display by a screen.
Definition: galleryviews.h:95
QPair< int, QString > ThumbPair
Definition: imagetypes.h:63
QHash< int, FileCacheEntry > m_fileCache
Caches displayed image files.
Definition: galleryviews.h:135
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:20
void ClearCache()
Clears UI cache.
QString GetPosition() const
Get positional status.
Provides view datastores for Gallery screens.
bool IsFor(int id)
Definition: galleryviews.h:37
QString ToString(int id) const
const double DEFAULT_WEIGHT
Photos without an exif timestamp will default to the mode of the beta distribution.
QString m_thumbUrl
Definition: galleryviews.h:86
void PopulateThumbs(ImageItem &, int thumbsNeeded, const ImageList &files, const ImageList &dirs, int level=0)
Populate directory stats & thumbnails recursively from database as follows: Use user cover,...
QStringList ClearImage(int id, bool remove=false)
Clear file from UI cache and optionally from view.
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:128
int m_parentId
Id of parent dir.
Definition: imagetypes.h:103
void Initialise(int id)
Definition: galleryviews.h:35
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.
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:199
const double TRAILING_BETA_SHAPE
See LEADING_BETA_SHAPE.
DirectoryView(SlideOrderType)
Constructs a view of images & directories that can be marked.
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:22
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:21
void Invert(ImageIdList all)
Definition: galleryviews.h:40
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:18
QString GetPosition() const
Get positional status.
void Cache(ImageItemK &, int thumbCount)
Cache displayed dir.
QVector< double > WeightList
Seasonal weightings for images in a view.
Definition: galleryviews.h:27
void MarkAll()
Mark all images/dirs.
int m_userThumbnail
Id of thumbnail to use as cover (dirs only)
Definition: imagetypes.h:121
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
void Mark(int, bool)
Mark/unmark an image/dir.
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 LoadDirThumbs(ImageItem &, int thumbsNeeded, int level=0)
Populate thumbs for a dir.
void Populate(ImageList &files)
Fills view with Db images, re-ordering them as required.
void Clear()
Definition: galleryviews.h:36
QList< ThumbPair > m_thumbs
Definition: galleryviews.h:157
void Rotate(int id)
Rotate view so that starting image is at front.
QString ToString(int id)
Definition: galleryviews.h:81
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)
Records info of displayed image files to enable clean-up of the UI image cache.
Definition: galleryviews.h:73
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.
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:179
QList< ImagePtr > ImageList
Definition: imagetypes.h:174
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:127
int m_active
Sequence index of current selected image.
Definition: galleryviews.h:132
PictureAttribute next(PictureAttributeSupported supported, PictureAttribute attribute)
void SetDirectory(int)
Manage markings on tree navigation.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QSharedPointer< ImageItem > ImagePtr
Definition: imagetypes.h:173
bool PopulateFromCache(ImageItem &, int required)
Retrieve cached dir, if available.
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:127
#define PHOTO_DB_ID
Definition: imagetypes.h:28
void InvertMarked()
Mark all unmarked items, unmark all marked items.
QList< int > ImageIdList
Definition: imagetypes.h:59
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...
void Add(ImageIdList newIds)
Definition: galleryviews.h:38
MarkedFiles m_marked
Marked items in current dir/view.
Definition: galleryviews.h:198
Records dir info for every displayed dir.
Definition: galleryviews.h:142
ImageManagerFe & m_mgr
Definition: galleryviews.h:129
QHash< int, ImagePtrK > m_images
Image objects currently displayed.
Definition: galleryviews.h:130
int m_id
Uniquely identifies an image (file/dir).
Definition: imagetypes.h:96
QList< ImagePtrK > ImageListK
Definition: imagetypes.h:180
#define GALLERY_DB_ID
Definition: imagetypes.h:26
SlideOrderType m_order
Definition: galleryviews.h:128
ImageIdList GetChildren() const
Definition: galleryviews.h:194
QHash< int, DirCacheEntry > m_dirCache
Caches displayed image dirs.
Definition: galleryviews.h:202
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:19
A snapshot of current selection, markings & dir info when menu is invoked.
Definition: galleryviews.h:49