MythTV  master
galleryslide.cpp
Go to the documentation of this file.
1 #include "galleryslide.h"
2 
3 #include <cmath> // for roundf
4 #include "mythmainwindow.h"
5 #include "mythlogging.h"
6 
7 #include "imagemetadata.h"
8 
9 
10 #define LOC QString("Slide: ")
11 #define SBLOC QString("SlideBuffer: ")
12 
13 
14 // Number of slides to use for buffering image requests.
15 // When browsing quickly the buffer will load consecutive slides until it fills.
16 // If too large, rapid browsing will be stodgy (sequential access) for images that
17 // aren't cached (Cached images are always fast).
18 // If too small, rapid browsing will result in skipping slides rather than flicking
19 // quickly through them.
20 // Minimum is 4: 3 for displaying a transition, 1 to handle load requests
21 #define SLIDE_BUFFER_SIZE 9
22 
23 
29 void AbstractAnimation::Start(bool forwards, float speed)
30 {
31  m_forwards = forwards;
32  m_speed = speed;
33  m_running = true;
34 }
35 
36 
45 void Animation::Set(const QVariant& from, const QVariant& to, int duration,
46  const QEasingCurve& curve, UIEffects::Centre centre)
47 {
48  setStartValue(from);
49  setEndValue(to);
50  m_centre = centre;
51  setDuration(duration);
52  setEasingCurve(curve);
53 }
54 
55 
61 void Animation::Start(bool forwards, float speed)
62 {
63  if (duration() == 0)
64  return;
65 
66  m_elapsed = forwards ? 0 : duration();
67  setCurrentTime(m_elapsed);
68 
69  AbstractAnimation::Start(forwards, speed);
70 }
71 
72 
77 void Animation::Pulse(int interval)
78 {
79  if (!m_running)
80  return;
81 
82  m_elapsed += (m_forwards ? interval : -interval) * m_speed;
83 
84  setCurrentTime(m_elapsed);
85 
86  // Detect completion
87  if ((m_forwards && m_elapsed >= duration())
88  || (!m_forwards && m_elapsed <= 0))
89  Finished();
90 }
91 
92 
97 void Animation::updateCurrentValue(const QVariant &value)
98 {
99  if (m_parent && m_running)
100  {
102 
103  switch (m_type)
104  {
105  case None: break;
106  case Position: m_parent->SetPosition(value.toPoint()); break;
107  case Alpha: m_parent->SetAlpha(value.toInt()); break;
108  case Zoom: m_parent->SetZoom(value.toFloat()); break;
109  case HorizontalZoom: m_parent->SetHorizontalZoom(value.toFloat()); break;
110  case VerticalZoom: m_parent->SetVerticalZoom(value.toFloat()); break;
111  case Angle: m_parent->SetAngle(value.toFloat()); break;
112  }
113  }
114 }
115 
116 
122 {
123  // Signal group when child completes
124  m_group.append(child);
125  connect(child, SIGNAL(finished()), this, SLOT(Finished()));
126 }
127 
128 
133 {
134  qDeleteAll(m_group);
135  m_group.clear();
136 }
137 
138 
143 void SequentialAnimation::Pulse(int interval)
144 {
145  if (!m_running || m_current < 0 || m_current >= m_group.size())
146  return;
147 
148  // Pulse current running child
149  m_group.at(m_current)->Pulse(interval);
150 }
151 
152 
158 void SequentialAnimation::Start(bool forwards, float speed)
159 {
160  if (m_group.empty())
161  return;
162 
163  m_current = forwards ? 0 : m_group.size() - 1;
164 
165  // Start group, then first child
166  GroupAnimation::Start(forwards, speed);
167  m_group.at(m_current)->Start(m_forwards, m_speed);
168 }
169 
170 
176 {
177  // Set group speed for subsequent children
179 
180  // Set active child
181  if (!m_running || m_current < 0 || m_current >= m_group.size())
182  return;
183 
184  m_group.at(m_current)->SetSpeed(speed);
185 }
186 
187 
192 {
193  // Finish group when last child finishes
194  if ((m_forwards && ++m_current == m_group.size())
195  || (!m_forwards && --m_current < 0))
197  else
198  // Start next child
199  m_group.at(m_current)->Start(m_forwards, m_speed);
200 }
201 
202 
207 void ParallelAnimation::Pulse(int interval)
208 {
209  if (m_running)
210  {
211  // Pulse all children
212  foreach(AbstractAnimation *animation, m_group)
213  animation->Pulse(interval);
214  }
215 }
216 
217 
223 void ParallelAnimation::Start(bool forwards, float speed)
224 {
225  if (m_group.empty())
226  return;
227 
228  m_finished = m_group.size();
229 
230  // Start group, then all children
231  GroupAnimation::Start(forwards, speed);
232  foreach(AbstractAnimation *animation, m_group)
233  animation->Start(m_forwards, m_speed);
234 }
235 
236 
242 {
243  // Set group speed, then all children
245  foreach(AbstractAnimation *animation, m_group)
246  animation->SetSpeed(m_speed);
247 }
248 
249 
254 {
255  // Finish group when last child finishes
256  if (--m_finished == 0)
258 }
259 
260 
265 void PanAnimation::updateCurrentValue(const QVariant &value)
266 {
267  if (m_parent && m_running)
268  {
269  Slide *image = m_parent;
270  image->SetPan(value.toPoint());
271  }
272 }
273 
274 
281 Slide::Slide(MythUIType *parent, const QString& name, MythUIImage *image)
282  : MythUIImage(parent, name)
283 {
284  // Clone from image
285  CopyFrom(image);
286 
287  // Null parent indicates we should become a child of the image (after
288  // copy to avoid recursion)
289  if (!parent)
290  {
291  // Slides sit on top of parent image area
292  SetArea(MythRect(image->GetArea().toQRect()));
293  m_Area.moveTo(0, 0);
294  setParent(image);
295  m_Parent = image;
296  image->AddChild(this);
297  }
298 
299  // Provide animations for pan & zoom
300  if (GetPainter()->SupportsAnimation())
301  {
303  m_panAnimation = new PanAnimation(this);
304  }
305 
306  connect(this, SIGNAL(LoadComplete()), this, SLOT(SlideLoaded()));
307 }
308 
309 
314 {
315  delete m_zoomAnimation;
316  delete m_panAnimation;
317  LOG(VB_GUI, LOG_DEBUG, "Deleted Slide " + objectName());
318 }
319 
320 
325 {
326  m_state = kEmpty;
327  m_data.clear();
328  m_waitingFor.clear();
329  SetCropRect(0, 0, 0, 0);
330  SetVisible(false);
331 }
332 
333 
338 QChar Slide::GetDebugState() const
339 {
340  switch (m_state)
341  {
342  case kEmpty: return 'e';
343  case kFailed: return 'f';
344  case kLoaded: return m_waitingFor ? 'r' : 'a';
345  case kLoading: return m_waitingFor ? 'l' : 'p';
346  }
347  return '?';
348 }
349 
350 
363 bool Slide::LoadSlide(const ImagePtrK& im, int direction, bool notifyCompletion)
364 {
365  m_direction = direction;
366  m_waitingFor = notifyCompletion ? im : ImagePtrK();
367 
368  if (im == m_data)
369  {
370  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Already loading/loaded %1 in %2")
371  .arg(im->m_filePath, objectName()));
372 
373  if (m_state >= kLoaded && notifyCompletion)
374  // Image has been pre-loaded
375  emit ImageLoaded(this);
376 
377  return (m_state >= kLoaded);
378  }
379 
380  // Is a different image loading ?
381  if (m_state == kLoading)
382  {
383  // Can't abort image loads, so must wait for it to finish
384  // before starting new load
385  m_waitingFor = im;
386 
387  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Postponing load of %1 in %2")
388  .arg(im->m_filePath, objectName()));
389 
390  return false;
391  }
392 
393  // Start load
394  m_data = im;
395  m_state = kLoading;
396 
397  if (im->m_type == kVideoFile)
398  {
399  // Use thumbnail, which has already been orientated
400  SetFilename(im->m_thumbNails.at(0).second);
401  SetOrientation(1);
402  }
403  else
404  {
405  // Load image, compensating for any Qt auto-orientation
406  SetFilename(im->m_url);
407  SetOrientation(Orientation(m_data->m_orientation).GetCurrent(true));
408  }
409 
410  // Load in background
411  Load(true);
412  return false;
413 }
414 
415 
423 {
424  m_state = m_Images[0] ? kLoaded : kFailed;
425  if (m_state == kFailed)
426  LOG(VB_GENERAL, LOG_ERR, LOC +
427  QString("Failed to load %1").arg(m_data->m_filePath));
428 
429  // Ignore superseded requests and preloads
430  if (m_data == m_waitingFor)
431  {
432  // Loaded image is the latest requested
433  emit ImageLoaded(this);
434  }
435  else if (m_waitingFor)
436  {
437  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Starting delayed load %1")
438  .arg(m_waitingFor->m_filePath));
439 
440  // Start latest postponed load
442  }
443 }
444 
445 
451 void Slide::Zoom(int percentage)
452 {
453  // Sentinel indicates reset to default zoom
454  float newZoom = (percentage == 0)
455  ? 1.0F
456  : qMax(MIN_ZOOM,
457  qMin(MAX_ZOOM, m_zoom * (1.0F + percentage / 100.0F)));
458  if (newZoom != m_zoom)
459  {
460  if (m_zoomAnimation)
461  {
462  m_zoomAnimation->Set(m_zoom, newZoom, 250, QEasingCurve::OutQuad);
464  }
465  else
466  SetZoom(newZoom);
467  }
468 }
469 
470 
477 void Slide::SetZoom(float zoom)
478 {
479  m_zoom = zoom;
481 
482  // TODO
483  // MythUIImage displaces widget or doesn't centre for some combinations of
484  // zoom centre/cropping so frig centre for now.
486 
487  SetPan(m_pan);
488 }
489 
490 
495 void Slide::Pan(QPoint offset)
496 {
497  // Panning only possible when zoomed in
498  if (m_zoom > 1.0F)
499  {
500  QPoint start = m_pan;
501 
502  // Sentinel indicates reset to centre
503  // Panning is applied to original (unzoomed) image co-ords.
504  // Adjust offset for zoom so that pan moves a constant screen distance rather
505  // than constant image distance
506  QPoint dest = offset.isNull() ? QPoint(0, 0) : start + offset / m_zoom;
507 
508  if (m_panAnimation)
509  {
510  m_panAnimation->Set(start, dest, 250, QEasingCurve::Linear);
512  }
513  else
514  SetPan(dest);
515  }
516 }
517 
518 
525 void Slide::SetPan(QPoint pos)
526 {
527  if (m_state == kFailed)
528  {
529  m_pan = pos;
530  return;
531  }
532 
533  // Determine zoom of largest dimension
534  QRect imageArea = m_Images[m_CurPos]->rect();
535  float hRatio = float(imageArea.height()) / m_Area.height();
536  float wRatio = float(imageArea.width()) / m_Area.width();
537  float ratio = qMax(hRatio, wRatio);
538 
539  if (m_zoom != 0.0F)
540  ratio /= m_zoom;
541 
542  // Determine crop area
543  int h = qMin(int(roundf(m_Area.height() * ratio)), imageArea.height());
544  int w = qMin(int(roundf(m_Area.width() * ratio)), imageArea.width());
545  int x = imageArea.center().x() - w / 2;
546  int y = imageArea.center().y() - h / 2;
547 
548  // Constrain pan to boundaries
549  int limitX = (imageArea.width() - w) / 2;
550  int limitY = (imageArea.height() - h) / 2;
551  m_pan.setX(qMax(qMin(pos.x(), limitX), -limitX));
552  m_pan.setY(qMax(qMin(pos.y(), limitY), -limitY));
553 
554  SetCropRect(x + m_pan.x(), y + m_pan.y(), w, h);
555  SetRedraw();
556 }
557 
558 
563 {
564  // Update zoom/pan animations
565  if (m_zoomAnimation)
566  m_zoomAnimation->Pulse(GetMythMainWindow()->GetDrawInterval());
567 
568  if (m_panAnimation)
569  m_panAnimation->Pulse(GetMythMainWindow()->GetDrawInterval());
570 }
571 
572 
574 {
575  LOG(VB_GUI, LOG_DEBUG, "Deleted Slidebuffer");
576 }
577 
578 
580 {
581  QMutexLocker lock(&m_mutexQ);
582  foreach (Slide *s, m_queue)
583  s->Clear();
584  LOG(VB_GUI, LOG_DEBUG, "Aborted Slidebuffer");
585 }
586 
587 
594 {
595  // Require at least 4 slides: 2 for transitions, 1 to handle further requests
596  // and 1 to prevent solitary slide from being used whilst it is loading
597  int size = qMax(SLIDE_BUFFER_SIZE, 4);
598 
599  // Fill buffer with slides cloned from the XML image widget
600 
601  // Create first as a child of the XML image.
602  auto *slide = new Slide(nullptr, "slide0", &image);
603 
604  // Buffer is notified when it has loaded image
605  connect(slide, SIGNAL(ImageLoaded(Slide *)),
606  this, SLOT(Flush(Slide *)));
607 
608  m_queue.enqueue(slide);
609 
610  // Rest are simple clones of first
611  for (int i = 1; i < size; ++i)
612  {
613  slide = new Slide(&image, QString("slide%1").arg(i), slide);
614 
615  // All slides (except first) start off hidden
616  slide->SetVisible(false);
617 
618  // Buffer is notified when it has loaded image
619  connect(slide, SIGNAL(ImageLoaded(Slide *)),
620  this, SLOT(Flush(Slide *)));
621 
622  m_queue.enqueue(slide);
623  }
624 
625  m_nextLoad = 1;
626 }
627 
628 
634 {
635  QMutexLocker lock(&m_mutexQ);
636 
637  QString state;
638  for (int i = 0; i < m_queue.size(); ++i)
639  {
640  QChar code(m_queue.at(i)->GetDebugState());
641  state += (i == m_nextLoad ? code.toUpper() : code);
642  }
643  return QString("[%1] (%2)").arg(state, m_queue.head()->objectName());
644 }
645 
646 
654 bool SlideBuffer::Load(const ImagePtrK& im, int direction)
655 {
656  if (!im)
657  return false;
658 
659  QMutexLocker lock(&m_mutexQ);
660 
661  // Start loading image in next available slide
662  Slide *slide = m_queue.at(m_nextLoad);
663 
664  // Further load requests will go to same slide if no free ones are available
665  if (m_nextLoad < m_queue.size() - 1)
666  ++m_nextLoad;
667 
668  LOG(VB_FILE, LOG_DEBUG, SBLOC + QString("Loading %1 in %2, %3")
669  .arg(im->m_filePath, slide->objectName()).arg(BufferState()));
670 
671  return slide->LoadSlide(im, direction, true);
672 }
673 
674 
680 {
681  if (!im)
682  return;
683 
684  QMutexLocker lock(&m_mutexQ);
685 
686  // Start loading image in next available slide
687  Slide *slide = m_queue.at(m_nextLoad);
688 
689  LOG(VB_FILE, LOG_DEBUG, SBLOC + QString("Preloading %1 in %2, %3")
690  .arg(im->m_filePath, slide->objectName()).arg(BufferState()));
691 
692  // Load silently
693  slide->LoadSlide(im);
694 }
695 
696 
702 {
703  QMutexLocker lock(&m_mutexQ);
704 
705  // Reset slide & return to buffer for re-use
706  Slide *slide = m_queue.dequeue();
707  slide->Clear();
708  m_queue.enqueue(slide);
709 
710  QString name = slide->objectName();
711 
712  // Free constrained load ptr now a spare slide is available
713  if (!m_queue.at(--m_nextLoad)->IsEmpty())
714  ++m_nextLoad;
715 
716  LOG(VB_FILE, LOG_DEBUG, SBLOC + QString("Released %1").arg(name));
717 
718  // Flush any pending slides that originate from multiple requests (skipping)
719  Flush(m_queue.head(), "Pending");
720 }
721 
722 
729 void SlideBuffer::Flush(Slide *slide, const QString& reason)
730 {
731  QMutexLocker lock(&m_mutexQ);
732 
733  // Determine number of consecutive slides that are now available after head
734  // Include last slide to ensure transition speed is consistent: it will never
735  // be displayed because queue size is always > 2
736  int available = 1;
737  while (available < m_queue.size() && m_queue.at(available)->IsLoaded())
738  ++available;
739 
740  if (available == 1)
741  return;
742 
743  // Notify that more slides are available
744  ImagePtrK im = slide->GetImageData();
745  QString path = im ? im->m_filePath : "Unknown";
746 
747  LOG(VB_FILE, LOG_DEBUG, SBLOC + QString("%1 %2 in %3, %4")
748  .arg(reason, path, slide->objectName()).arg(BufferState()));
749 
750  emit SlideReady(--available);
751 }
void SetSpeed(float speed) override
Change speed of group and all child animations.
A video.
Definition: imagetypes.h:39
QPoint m_pan
Pan position (0,0) = no pan.
Definition: galleryslide.h:199
void SetZoom(float zoom)
Sets slide zoom.
PanAnimation * m_panAnimation
Dedicated animation for panning, if supported.
Definition: galleryslide.h:198
int m_elapsed
Current millisec position within animation, 0..duration.
Definition: galleryslide.h:85
Encapsulates Exif orientation processing.
Definition: imagemetadata.h:62
virtual MythPainter * GetPainter(void)
void finished()
Signals animation has finished.
void SetVerticalZoom(float zoom)
Definition: mythuitype.cpp:956
void Pulse() override
Update pan & zoom animations.
void SlideLoaded()
An image has completed loading.
virtual void Finished()
To be called when animation completes.
Definition: galleryslide.h:40
virtual void Add(AbstractAnimation *child)
Add child animation to group.
Slide(MythUIType *parent, const QString &name, MythUIImage *image)
Clone slide from a theme MythUIImage.
Specialised animation for panning slideshow images (MythUI doesn't support panning)
Definition: galleryslide.h:147
void SetAlpha(int newalpha)
Definition: mythuitype.cpp:925
void SetRedraw(void)
Definition: mythuitype.cpp:293
bool m_forwards
Play direction.
Definition: galleryslide.h:47
Image widget, displays a single image or multiple images in sequence.
Definition: mythuiimage.h:97
void Start(bool forwards, float speed=1.0) override
Start sequential animation.
void Finished() override
A child animation has completed.
virtual void Pulse(int interval)=0
Base animation class that is driven by a Myth pulse and implements variable speed.
Definition: galleryslide.h:27
#define MAX_ZOOM
Definition: galleryslide.h:21
void SetCropRect(int x, int y, int width, int height)
Crop the image using the given rectangle, useful for removing unsightly edges from imported images or...
void SetHorizontalZoom(float zoom)
Definition: mythuitype.cpp:950
int m_nextLoad
Index of first spare slide, (or last slide if none spare)
Definition: galleryslide.h:252
bool Load(const ImagePtrK &im, int direction)
Assign an image to next available slide, start loading and signal when done.
ImagePtrK m_data
The image currently loading/loaded.
Definition: galleryslide.h:191
void updateCurrentValue(const QVariant &value) override
Update pan value.
UIEffects m_Effects
Definition: mythuitype.h:257
The base class on which all widgets and screens are based.
Definition: mythuitype.h:63
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void ReleaseCurrent()
Move head slide to back of queue and flush waiting slides.
void SetPosition(int x, int y)
Convenience method, calls SetPosition(const MythPoint&) Override that instead to change functionality...
Definition: mythuitype.cpp:517
Handles Exif/FFMpeg metadata tags for images.
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:172
virtual void Start(bool forwards, float speed=1.0)
Initialise & start base animation.
void CopyFrom(MythUIType *base) override
Copy this widgets state from another.
Centre m_centre
void SetOrientation(int orientation)
Saves the exif orientation value of the first image in the widget.
float m_zoom
Current zoom, 1.0 = fullsize.
Definition: galleryslide.h:194
ImagePtrK GetImageData() const
Definition: galleryslide.h:165
virtual void SetVisible(bool visible)
void Flush(Slide *slide, const QString &reason="Loaded")
Signal if any slides are waiting to be displayed.
void Pulse(int interval) override
Progress sequential animation.
QRect toQRect(void) const
Definition: mythrect.cpp:362
bool m_running
True whilst animation is active.
Definition: galleryslide.h:48
void Finished() override
A child animation has completed.
void Initialise(MythUIImage &image)
Construct buffer.
void updateCurrentValue(const QVariant &value) override
Update animated value.
void Preload(const ImagePtrK &im)
Load an image in next available slide.
int GetCurrent(bool compensate)
Determines orientation required for an image.
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:864
void SetSpeed(float speed) override
Definition: galleryslide.h:98
QMutex m_mutexQ
Queue protection.
Definition: galleryslide.h:250
void Pan(QPoint offset)
Initiate pan.
Defines specialised images used by the Gallery slideshow and the animation framework used by transfor...
virtual void SetSpeed(float speed)
Definition: galleryslide.h:34
Wrapper around QRect allowing us to handle percentage and other relative values for areas in mythui.
Definition: mythrect.h:17
SlideState m_state
Slide validity.
Definition: galleryslide.h:190
bool LoadSlide(const ImagePtrK &im, int direction=0, bool notifyCompletion=false)
Load slide with an image.
float m_speed
Real-time = 1.0, Double-speed = 2.0.
Definition: galleryslide.h:49
MythRect m_Area
Definition: mythuitype.h:249
QList< AbstractAnimation * > m_group
Definition: galleryslide.h:104
QChar GetDebugState() const
Return debug status.
void SetSpeed(float speed) override
Change speed of current child animation and all subsequent ones.
void Clear()
Reset slide to unused state.
void SetPan(QPoint pos)
Sets slide pan.
void ImageLoaded(Slide *)
Generated when the last requested image has loaded.
#define SBLOC
#define MIN_ZOOM
Definition: galleryslide.h:20
MythMainWindow * GetMythMainWindow(void)
Slide * m_parent
Image to be animated.
Definition: galleryslide.h:80
void LoadComplete()
virtual void SetArea(const MythRect &rect)
Definition: mythuitype.cpp:589
void Start(bool forwards, float speed=1.0) override
Initialise & start base animation.
Definition: galleryslide.h:96
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void Zoom(int percentage)
Initiate slide zoom.
A specialised image for slideshows.
Definition: galleryslide.h:156
int m_direction
Navigation that created this image, -1 = Prev, 0 = Update, 1 = Next.
Definition: galleryslide.h:196
#define LOC
QQueue< Slide * > m_queue
Queue of slides.
Definition: galleryslide.h:251
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
ImagePtrK m_waitingFor
The most recently requested image. Null for preloads. Differs from m_data when skipping.
Definition: galleryslide.h:193
QHash< int, MythImage * > m_Images
Definition: mythuiimage.h:170
A single animation controlling alpha, zoom, rotation and position.
Definition: galleryslide.h:55
#define SLIDE_BUFFER_SIZE
~SlideBuffer() override
MythUIType * m_Parent
Definition: mythuitype.h:270
unsigned int m_CurPos
Definition: mythuiimage.h:178
Animation * m_zoomAnimation
Dedicated animation for zoom, if supported.
Definition: galleryslide.h:197
void Set(const QVariant &from, const QVariant &to, int duration=500, const QEasingCurve &curve=QEasingCurve::InOutCubic, UIEffects::Centre centre=UIEffects::Middle)
Initialises an animation.
void Start(bool forwards, float speed=1.0) override
Start parallel group. All children play simultaneously.
int m_current
Index of child currently playing.
Definition: galleryslide.h:123
void Pulse(int interval) override
Progress parallel animations.
void Pulse(int interval) override
Progress single animation.
QString BufferState()
Determines buffer state for debug logging.
void SetAngle(float angle)
Definition: mythuitype.cpp:962
void Clear() override
Delete all child animations.
int m_finished
Count of child animations that have finished.
Definition: galleryslide.h:141
UIEffects::Centre m_centre
Definition: galleryslide.h:82
~Slide() override
Destructor.
void SetCentre(UIEffects::Centre centre)
Definition: mythuitype.cpp:939
void Start(bool forwards=true, float speed=1.0) override
Start a single animation.
void AddChild(MythUIType *child)
Add a child UIType.
Definition: mythuitype.cpp:85
void SlideReady(int count)
Signals that buffer has (count) loaded slides awaiting display.
Type m_type
Definition: galleryslide.h:81