MythTV  master
singleview.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 /* ============================================================
3  * File : singleview.cpp
4  * Description :
5  *
6  * Copyright 2004-2006 Renchi Raju, Daniel Kristjansson
7  *
8  * This program is free software; you can redistribute it
9  * and/or modify it under the terms of the GNU General
10  * Public License as published bythe Free Software Foundation;
11  * either version 2, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * ============================================================ */
20 
21 // ANSI C headers
22 #include <cmath>
23 
24 // C++ headers
25 #include <iostream>
26 using namespace std;
27 
28 // Qt headers
29 #include <QImage>
30 #include <QTimer>
31 #include <QPainter>
32 #include <QKeyEvent>
33 #include <QPixmap>
34 #include <QPaintEvent>
35 
36 // MythTV plugin headers
37 #include <mythuihelper.h>
38 #include <mythcontext.h>
39 #include <mythdate.h>
40 
41 // MythGallery headers
42 #include "singleview.h"
43 #include "galleryutil.h"
44 
45 #define LOC QString("QtView: ")
46 
47 template<typename T> T sq(T val) { return val * val; }
48 
50  const ThumbList& itemList, int *pos,
51  int slideShow, int sortorder,
52  MythMainWindow *parent,
53  const char *name)
54  : MythDialog(parent, name),
55  ImageView(itemList, pos, slideShow, sortorder),
56 
57  // Caption variables
58  m_caption_timer(new QTimer(this))
59 {
60  m_scaleMax = (ScaleMax) gCoreContext->GetNumSetting("GalleryScaleMax", 0);
61 
62  m_slideshow_timer = new QTimer(this);
64 
65  // --------------------------------------------------------------------
66 
67  QString transType = gCoreContext->GetSetting("SlideshowTransition");
68  if (!transType.isEmpty() && m_effect_map.contains(transType))
69  m_effect_method = m_effect_map[transType];
70 
71  if (m_effect_method.isEmpty() || transType == "random")
72  {
74  m_effect_random = true;
75  }
76 
77  // ---------------------------------------------------------------
78 
79  m_caption_show = gCoreContext->GetNumSetting("GalleryOverlayCaption", 0);
80  if (m_caption_show)
81  {
83  m_caption_restore_pixmap = new QPixmap(m_screenwidth, 100);
84  }
85 
86  // --------------------------------------------------------------------
87 
88  setNoErase();
89  QString bgtype = gCoreContext->GetSetting("SlideshowBackground");
90  if (bgtype != "theme" && !bgtype.isEmpty())
91  setPalette(QPalette(QColor(bgtype)));
92 
93  // --------------------------------------------------------------------
94 
95  connect(m_slideshow_timer, SIGNAL(timeout()), SLOT(SlideTimeout()));
96  connect(m_caption_timer, SIGNAL(timeout()), SLOT(CaptionTimeout()));
97 
98  // --------------------------------------------------------------------
99 
101 
102  // --------------------------------------------------------------------
103 
104  if (slideShow)
105  {
107  m_slideshow_running = true;
108  m_slideshow_timer->stop();
109  m_slideshow_timer->setSingleShot(true);
112  }
113 }
114 
116 {
118  {
121  }
122 
123  if (m_effect_painter)
124  {
125  if (m_effect_painter->isActive())
126  m_effect_painter->end();
127 
128  delete m_effect_painter;
129  m_effect_painter = nullptr;
130  }
131 
132  SetPixmap(nullptr);
133 
134  if (m_effect_pixmap)
135  {
136  delete m_effect_pixmap;
137  m_effect_pixmap = nullptr;
138  }
139 
140  if (m_info_pixmap)
141  {
142  delete m_info_pixmap;
143  m_info_pixmap = nullptr;
144  }
145 
146  // save the current m_scaleMax setting so we can restore it later
147  gCoreContext->SaveSetting("GalleryScaleMax", m_scaleMax);
148 }
149 
150 void SingleView::paintEvent(QPaintEvent * /*e*/)
151 {
152  if (1 == m_movieState)
153  {
154  m_movieState = 2;
155 
156  ThumbItem *item = getCurrentItem();
157 
158  if (item)
160 
161  if (!m_slideshow_running && item)
162  {
163  QImage image;
164  GetScreenShot(image, item);
165  if (image.isNull())
166  return;
167 
168  image = image.scaled(800, 600);
169 
170  // overlay "Press SELECT to play again" text
171  QPainter p(&image);
172  QRect rect = QRect(20, image.height() - 100,
173  image.width() - 40, 80);
174  p.fillRect(rect, QBrush(QColor(0,0,0,100)));
175  p.setFont(QFont("Arial", 25, QFont::Bold));
176  p.setPen(QColor(255,255,255));
177  p.drawText(rect, Qt::AlignCenter, tr("Press SELECT to play again"));
178  p.end();
179 
180  m_image = image;
181  SetZoom(1.0);
182  }
183  }
184 
185  if (!m_effect_running)
186  {
187  QPixmap pix(m_screenwidth, m_screenheight);
188  pix.fill(QWidget::palette().color(this->backgroundRole()));
189 
190  if (m_pixmap)
191  {
192  if (m_pixmap->width() <= m_screenwidth &&
193  m_pixmap->height() <= m_screenheight)
194  {
195  QPainter p(&pix);
196  p.drawPixmap(QPoint((m_screenwidth - m_pixmap->width()) >> 1,
197  (m_screenheight - m_pixmap->height()) >> 1),
198  *m_pixmap, QRect(0,0,-1,-1));
199  }
200  else
201  {
202  QPainter p(&pix);
203  p.drawPixmap(QPoint(0,0),
204  *m_pixmap, QRect(m_source_loc, pix.size()));
205  }
206 
207  if (m_caption_remove)
208  {
209  m_caption_remove = false;
210  QPainter p(this);
211  p.drawPixmap(QPoint(0, m_screenheight - 100),
212  *m_caption_restore_pixmap, QRect(0,0,-1,-1));
213  p.end();
214  }
215  else if (m_caption_show && !m_caption_timer->isActive())
216  {
217  ThumbItem *item = getCurrentItem();
218  if (!item->HasCaption())
219  item->InitCaption(true);
220 
221  if (item->HasCaption())
222  {
223  // Store actual background to restore later
224  QPainter sb(m_caption_restore_pixmap);
225  sb.drawPixmap(QPoint(0, 0),
226  pix,
227  QRect(0, m_screenheight - 100,
228  m_screenwidth, 100));
229  sb.end();
230 
231  // Blit semi-transparent background into place
232  QPainter pbg(&pix);
233  pbg.drawPixmap(QPoint(0, m_screenheight - 100),
235  QRect(0, 0, m_screenwidth, 100));
236  pbg.end();
237 
238  // Draw caption
239  QPainter p(&pix);
240  p.initFrom(this);
241  p.drawText(0, m_screenheight - 100, m_screenwidth, 100,
242  Qt::AlignCenter, item->GetCaption());
243  p.end();
244 
245  m_caption_timer->stop();
246  m_caption_timer->setSingleShot(true);
247  m_caption_timer->start(m_caption_show * 1000);
248  }
249  }
250 
251  if (m_zoom != 1.0F)
252  {
253  QPainter p(&pix);
254  p.initFrom(this);
255  p.drawText(m_screenwidth / 10, m_screenheight / 10,
256  QString::number(m_zoom) + "x Zoom");
257  p.end();
258  }
259 
261  {
262  if (!m_info_pixmap)
263  {
265  m_screenwidth - 2 * m_screenwidth / 10,
266  m_screenheight - 2 * m_screenheight / 10));
267  }
268 
269  QPainter ip(&pix);
270  ip.drawPixmap(QPoint(m_screenwidth / 10, m_screenheight / 10),
271  *m_info_pixmap, QRect(0,0,-1,-1));
272  ip.end();
273 
274  QPainter p(&pix);
275  p.initFrom(this);
276  ThumbItem *item = getCurrentItem();
277  QString info;
278  if (item)
279  {
280  info = item->GetDescription(GetDescriptionStatus(),
281  m_image.size(), m_angle);
282  }
283 
284  if (!info.isEmpty())
285  {
286  p.drawText(m_screenwidth / 10 + (int)(10 * m_wmult),
287  m_screenheight / 10 + (int)(10 * m_hmult),
288  m_info_pixmap->width() - 2 * (int)(10 * m_wmult),
289  m_info_pixmap->height() - 2 * (int)(10 * m_hmult),
290  Qt::AlignLeft, info);
291  }
292  p.end();
293  }
294 
295  }
296 
297  QPainter p(this);
298  p.drawPixmap(QPoint(0,0), pix, QRect(0,0,-1,-1));
299  p.end();
300  }
301  else if (!m_effect_method.isEmpty())
303 }
304 
305 void SingleView::keyPressEvent(QKeyEvent *e)
306 {
307  bool handled = false;
308 
311  bool wasRunning = m_slideshow_running;
312  m_slideshow_timer->stop();
313  m_caption_timer->stop();
314  m_slideshow_running = false;
316  m_effect_running = false;
318  if (m_effect_painter && m_effect_painter->isActive())
319  m_effect_painter->end();
320 
321  bool wasInfo = m_info_show;
322  m_info_show = false;
323  bool wasInfoShort = m_info_show_short;
324  m_info_show_short = false;
325 
326  QStringList actions;
327  handled = GetMythMainWindow()->TranslateKeyPress("Gallery", e, actions);
328 
329  int scrollX = m_screenwidth / 10;
330  int scrollY = m_screenheight / 10;
331 
332  for (unsigned int i = 0; i < (unsigned int) actions.size() && !handled; i++)
333  {
334  QString action = actions[i];
335  handled = true;
336 
337  if (action == "LEFT" || action == "UP")
338  {
339  m_info_show = wasInfo;
340  m_slideshow_running = wasRunning;
341  DisplayPrev(true, true);
342  }
343  else if (action == "RIGHT" || action == "DOWN")
344  {
345  m_info_show = wasInfo;
346  m_slideshow_running = wasRunning;
347  DisplayNext(true, true);
348  }
349  else if (action == "ZOOMOUT")
350  {
351  if (m_zoom > 0.5F)
352  {
353  SetZoom(m_zoom - 0.5F);
354  if (m_zoom > 1.0F)
355  {
356  m_source_loc.setY(m_source_loc.y() - (m_screenheight / 4));
357  m_source_loc.setX(m_source_loc.x() - (m_screenwidth / 4));
358  CheckPosition();
359  }
360  else
361  m_source_loc = QPoint(0, 0);
362  }
363  }
364  else if (action == "ZOOMIN")
365  {
366  if (m_zoom < 4.0F)
367  {
368  SetZoom(m_zoom + 0.5F);
369  if (m_zoom > 1.0F)
370  {
371  m_source_loc.setY(m_source_loc.y() + (m_screenheight / 4));
372  m_source_loc.setX(m_source_loc.x() + (m_screenwidth / 4));
373  CheckPosition();
374  }
375  else
376  m_source_loc = QPoint(0, 0);
377  }
378  }
379  else if (action == "FULLSIZE")
380  {
381  m_source_loc = QPoint(0, 0);
382  if (m_zoom != 1.0F)
383  SetZoom(1.0F);
384  }
385  else if (action == "SCROLLLEFT")
386  {
387  if (m_zoom > 1.0F)
388  {
389  m_source_loc.setX(m_source_loc.x() - scrollX);
390  m_source_loc.setX(
391  (m_source_loc.x() < 0) ? 0 : m_source_loc.x());
392  }
393  }
394  else if (action == "SCROLLRIGHT")
395  {
396  if (m_zoom > 1.0F && m_pixmap)
397  {
398  m_source_loc.setX(m_source_loc.x() + scrollX);
399  m_source_loc.setX(min(m_source_loc.x(),
400  m_pixmap->width() - m_screenwidth));
401  }
402  }
403  else if (action == "SCROLLDOWN")
404  {
405  if (m_zoom > 1.0F && m_pixmap)
406  {
407  m_source_loc.setY(m_source_loc.y() + scrollY);
408  m_source_loc.setY(min(m_source_loc.y(),
409  m_pixmap->height() - m_screenheight));
410  }
411  }
412  else if (action == "SCROLLUP")
413  {
414  if (m_zoom > 1.0F)
415  {
416  m_source_loc.setY(m_source_loc.y() - scrollY);
417  m_source_loc.setY(
418  (m_source_loc.y() < 0) ? 0 : m_source_loc.y());
419  }
420  }
421  else if (action == "RECENTER")
422  {
423  if (m_zoom > 1.0F && m_pixmap)
424  {
425  m_source_loc = QPoint(
426  (m_pixmap->width() - m_screenwidth) >> 1,
427  (m_pixmap->height() - m_screenheight) >> 1);
428  }
429  }
430  else if (action == "UPLEFT")
431  {
432  if (m_zoom > 1.0F)
433  {
434  m_source_loc = QPoint(0,0);
435  }
436  }
437  else if (action == "LOWRIGHT")
438  {
439  if (m_zoom > 1.0F && m_pixmap)
440  {
441  m_source_loc = QPoint(
442  m_pixmap->width() - scrollX - m_screenwidth,
443  m_pixmap->height() - scrollY - m_screenheight);
444  }
445  }
446  else if (action == "ROTRIGHT")
447  {
448  m_source_loc = QPoint(0, 0);
449  Rotate(90);
450  }
451  else if (action == "ROTLEFT")
452  {
453  m_source_loc = QPoint(0, 0);
454  Rotate(-90);
455  }
456  else if (action == "DELETE")
457  {
458  ThumbItem *item = getCurrentItem();
459  if (item && GalleryUtil::Delete(item->GetPath()))
460  {
461  item->SetPixmap(nullptr);
462  DisplayNext(true, true);
463  }
464  m_info_show = wasInfo;
465  m_slideshow_running = wasRunning;
466  }
467  else if (action == "PLAY" || action == "SLIDESHOW" ||
468  action == "RANDOMSHOW" || action == "SEASONALSHOW")
469  {
470  m_source_loc = QPoint(0, 0);
471  m_zoom = 1.0F;
472  m_angle = 0;
473  m_info_show = wasInfo;
474  m_info_show_short = true;
475  m_slideshow_running = !wasRunning;
476  }
477  else if (action == "INFO")
478  {
479  m_info_show = !wasInfo && !wasInfoShort;
480  m_slideshow_running = wasRunning;
481  }
482  else if (action == "FULLSCREEN")
483  {
485  m_source_loc = QPoint(0, 0);
486  SetZoom(1.0F);
487  }
488  else
489  {
490  handled = false;
491  }
492  }
493 
495  {
496  m_slideshow_timer->stop();
497  m_slideshow_timer->setSingleShot(true);
499  }
501  {
504  }
505 
506  update();
507 
508  if (!handled)
510 }
511 
513 {
514  m_source_loc.setX((m_source_loc.x() < 0) ? 0 : m_source_loc.x());
515  m_source_loc.setY((m_source_loc.y() < 0) ? 0 : m_source_loc.y());
516  m_source_loc.setX(min(m_source_loc.x(), m_pixmap->width() - m_screenwidth));
517  m_source_loc.setY(min(m_source_loc.y(), m_pixmap->height() - m_screenheight));
518 }
519 
520 void SingleView::DisplayNext(bool reset, bool loadImage)
521 {
522  if (reset)
523  {
524  m_angle = 0;
525  m_zoom = 1.0F;
526  m_source_loc = QPoint(0, 0);
527  }
528 
529  // Search for next item that hasn't been deleted.
530  // Close viewer in none remain.
531  int oldpos = m_pos;
532  while (true)
533  {
534  ThumbItem *item = advanceItem();
535  if (item)
536  {
537  if (QFile::exists(item->GetPath()))
538  {
539  break;
540  }
541  }
542  if (m_pos == oldpos)
543  {
544  // No valid items!!!
545  reject();
546  }
547  }
548 
549  if (loadImage)
550  Load();
551 }
552 
553 void SingleView::DisplayPrev(bool reset, bool loadImage)
554 {
555  if (reset)
556  {
557  m_angle = 0;
558  m_zoom = 1.0F;
559  m_source_loc = QPoint(0, 0);
560  }
561 
562  // Search for next item that hasn't been deleted.
563  // Close viewer in none remain.
564  int oldpos = m_pos;
565  while (true)
566  {
567  ThumbItem *item = retreatItem();
568  if (item && QFile::exists(item->GetPath()))
569  break;
570 
571  if (m_pos == oldpos)
572  {
573  // No valid items!!!
574  reject();
575  }
576  }
577 
578  if (loadImage)
579  Load();
580 }
581 
583 {
584  m_movieState = 0;
585 
586  SetPixmap(nullptr);
587 
588  ThumbItem *item = getCurrentItem();
589  if (!item)
590  {
591  LOG(VB_GENERAL, LOG_ERR, LOC + QString("No item at %1").arg(m_pos));
592  return;
593  }
594 
595  if (GalleryUtil::IsMovie(item->GetPath()))
596  {
597  m_movieState = 1;
598  return;
599  }
600 
601  m_image.load(item->GetPath());
602  if (m_image.isNull())
603  return;
604 
605  m_angle = item->GetRotationAngle();
606  if (m_angle != 0)
607  {
608  QMatrix matrix;
609  matrix.rotate(m_angle);
610  m_image = m_image.transformed(matrix, Qt::SmoothTransformation);
611  }
612 
613  SetZoom(m_zoom);
614 
615  UpdateLCD(item);
616 }
617 
618 void SingleView::Rotate(int angle)
619 {
620  m_angle += angle;
621 
622  m_angle = (m_angle >= 360) ? m_angle - 360 : m_angle;
623  m_angle = (m_angle < 0) ? m_angle + 360 : m_angle;
624 
625  ThumbItem *item = getCurrentItem();
626  if (item)
627  item->SetRotationAngle(m_angle);
628 
629  if (m_image.isNull())
630  return;
631 
632  QMatrix matrix;
633  matrix.rotate(angle);
634  m_image = m_image.transformed(matrix, Qt::SmoothTransformation);
635 
636  SetZoom(m_zoom);
637 }
638 
639 void SingleView::SetZoom(float zoom)
640 {
641  m_zoom = zoom;
642 
643  if (m_image.isNull())
644  return;
645 
646  QImage img = m_image;
647 
648  QSize dest = QSize(
649  (int)(m_screenwidth * m_zoom), (int)(m_screenheight * m_zoom));
650 
651  QSize sz = GalleryUtil::ScaleToDest(m_image.size(), dest, m_scaleMax);
652  if ((sz.width() > 0) && (sz.height() > 0))
653  img = m_image.scaled(sz, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
654 
655  SetPixmap(new QPixmap(QPixmap::fromImage(img)));
656 }
657 
658 void SingleView::SetPixmap(QPixmap *pixmap)
659 {
660  if (m_pixmap)
661  {
662  delete m_pixmap;
663  m_pixmap = nullptr;
664  }
665  m_pixmap = pixmap;
666 }
667 
668 QPixmap *SingleView::CreateBackground(const QSize &sz)
669 {
670  QImage img(sz.width(), sz.height(), QImage::Format_ARGB32);
671 
672  for (int y = 0; y < img.height(); y++)
673  {
674  for (int x = 0; x < img.width(); x++)
675  {
676  uint *p = (uint *)img.scanLine(y) + x;
677  *p = qRgba(0, 0, 0, 150);
678  }
679  }
680 
681  return new QPixmap(QPixmap::fromImage(img));
682 }
683 
685 {
686  m_effect_map.insert("none", "EffectNone");
687  m_effect_map.insert("chess board", "EffectChessboard");
688  m_effect_map.insert("melt down", "EffectMeltdown");
689  m_effect_map.insert("sweep", "EffectSweep");
690  m_effect_map.insert("noise", "EffectNoise");
691  m_effect_map.insert("growing", "EffectGrowing");
692  m_effect_map.insert("incoming edges", "EffectIncomingEdges");
693  m_effect_map.insert("horizontal lines", "EffectHorizLines");
694  m_effect_map.insert("vertical lines", "EffectVertLines");
695  m_effect_map.insert("circle out", "EffectCircleOut");
696  m_effect_map.insert("multicircle out", "EffectMultiCircleOut");
697  m_effect_map.insert("spiral in", "EffectSpiralIn");
698  m_effect_map.insert("blobs", "EffectBlobs");
699 }
700 
701 void SingleView::RunEffect(const QString &effect)
702 {
703  if (effect == "EffectChessboard")
705  else if (effect == "EffectMeltdown")
706  EffectMeltdown();
707  else if (effect == "EffectSweep")
708  EffectSweep();
709  else if (effect == "EffectNoise")
710  EffectNoise();
711  else if (effect == "EffectGrowing")
712  EffectGrowing();
713  else if (effect == "EffectIncomingEdges")
715  else if (effect == "EffectHorizLines")
717  else if (effect == "EffectVertLines")
718  EffectVertLines();
719  else if (effect == "EffectCircleOut")
720  EffectCircleOut();
721  else if (effect == "EffectMultiCircleOut")
723  else if (effect == "EffectSpiralIn")
724  EffectSpiralIn();
725  else if (effect == "EffectBlobs")
726  EffectBlobs();
727  else //if (effect == "EffectNone")
728  EffectNone();
729 }
730 
732 {
733  if (!m_effect_painter)
734  m_effect_painter = new QPainter();
735 
736  if (m_effect_painter->isActive())
737  m_effect_painter->end();
738 
739  QBrush brush;
740  if (m_effect_pixmap)
741  brush.setTexture(*m_effect_pixmap);
742 
743  m_effect_painter->begin(this);
744  m_effect_painter->setBrush(brush);
745  m_effect_painter->setPen(Qt::NoPen);
746 }
747 
749 {
750  if (!m_effect_pixmap)
752 
753  m_effect_pixmap->fill(QWidget::palette().color(this->backgroundRole()));
754 
755  if (m_pixmap)
756  {
757  QPoint src_loc((m_effect_pixmap->width() - m_pixmap->width() ) >> 1,
758  (m_effect_pixmap->height() - m_pixmap->height()) >> 1);
759  QPainter p(m_effect_pixmap);
760  p.drawPixmap(src_loc, *m_pixmap, QRect(0, 0, -1, -1));
761  p.end();
762  }
763 }
764 
766 {
767  m_effect_running = false;
769  update();
770 }
771 
773 {
774  if (m_effect_current_frame == 0)
775  {
776  m_effect_delta0 = QPoint(8, 8); // tile size
777  // m_effect_j = number of tiles
778  m_effect_j = (width() + m_effect_delta0.x() - 1) / m_effect_delta0.x();
779  m_effect_delta1 = QPoint(0, 0); // growing offsets from screen border
781 
782  // x = shrinking x-offset from screen border
783  // y = 0 or tile size for shrinking tiling effect
784  m_effect_bounds = QRect(
785  m_effect_j * m_effect_delta0.x(), (m_effect_j & 1) ? 0 : m_effect_delta0.y(),
786  width(), height());
787  }
788 
789  if (m_effect_delta1.x() >= m_effect_bounds.width())
790  {
791  m_effect_running = false;
793  update();
794  return;
795  }
796 
798  (m_effect_delta1.y()) ? 0 : m_effect_delta0.y());
799  QPoint t = QPoint(m_effect_bounds.x() - m_effect_delta0.x(),
800  (m_effect_bounds.y()) ? 0 : m_effect_delta0.y());
801  m_effect_bounds = QRect(t, m_effect_bounds.size());
802 
803  QPainter painter(this);
804  for (int y = 0; y < m_effect_bounds.width(); y += (m_effect_delta0.y()<<1))
805  {
806  QPoint src0(m_effect_delta1.x(), y + m_effect_delta1.y());
807  QRect dst0(m_effect_delta1.x(), y + m_effect_delta1.y(),
809  QPoint src1(m_effect_bounds.x(), y + m_effect_bounds.y());
810  QRect dst1(m_effect_bounds.x(), y + m_effect_bounds.y(),
812  painter.drawPixmap(src0, *m_effect_pixmap, dst0);
813  painter.drawPixmap(src1, *m_effect_pixmap, dst0);
814  }
815  painter.end();
816 
818 
820 }
821 
823 {
824  if (m_effect_current_frame == 0)
825  {
826  m_effect_subtype = random() % 4;
827  m_effect_delta0 = QPoint(
828  (kSweepLeftToRight == m_effect_subtype) ? 16 : -16,
829  (kSweepTopToBottom == m_effect_subtype) ? 16 : -16);
830  m_effect_bounds = QRect(
831  (kSweepLeftToRight == m_effect_subtype) ? 0 : width(),
832  (kSweepTopToBottom == m_effect_subtype) ? 0 : height(),
833  width(), height());
834  }
835 
838  {
839  // horizontal sweep
841  m_effect_bounds.x() < -64) ||
843  m_effect_bounds.x() > m_effect_bounds.width() + 64))
844  {
846  m_effect_running = false;
847  update();
848  return;
849  }
850 
851  int w, x, i;
852  QPainter p(this);
853  for (w = 2, i = 4, x = m_effect_bounds.x(); i > 0;
854  i--, w <<= 1, x -= m_effect_delta0.x())
855  {
856  p.drawPixmap(QPoint(x, 0), *m_effect_pixmap,
857  QRect(x, 0, w, m_effect_bounds.height()));
858  }
859  p.end();
860 
861  m_effect_bounds.moveLeft(m_effect_bounds.x() + m_effect_delta0.x());
862  }
863  else
864  {
865  // vertical sweep
867  m_effect_bounds.y() < -64) ||
869  m_effect_bounds.y() > m_effect_bounds.height() + 64))
870  {
872  m_effect_running = false;
873  update();
874  return;
875  }
876 
877  int h, y, i;
878  QPainter p(this);
879  for (h = 2, i = 4, y = m_effect_bounds.y(); i > 0;
880  i--, h <<= 1, y -= m_effect_delta0.y())
881  {
882  p.drawPixmap(QPoint(0, y), *m_effect_pixmap,
883  QRect(0, y, m_effect_bounds.width(), h));
884  }
885  p.end();
886 
888  }
889 
892 }
893 
895 {
896  if (m_effect_current_frame == 0)
897  {
898  m_effect_bounds = QRect(width() >> 1, height() >> 1, width(), height());
899  m_effect_i = 0;
900  m_effect_delta2_x = m_effect_bounds.x() * 0.01F;
901  m_effect_delta2_y = m_effect_bounds.y() * 0.01F;
902  }
903 
904  m_effect_bounds.moveTopLeft(
905  QPoint((m_effect_bounds.width() >> 1) - (int)(m_effect_i * m_effect_delta2_x),
906  (m_effect_bounds.height() >> 1) - (int)(m_effect_i * m_effect_delta2_y)));
907 
908  m_effect_i++;
909 
910  if (m_effect_bounds.x() < 0 || m_effect_bounds.y() < 0)
911  {
913  m_effect_running = false;
914  update();
915  return;
916  }
917 
918  QPainter p(this);
919  QSize dst_sz(m_effect_bounds.width() - (m_effect_bounds.x() << 1),
920  m_effect_bounds.height() - (m_effect_bounds.y() << 1));
921 
922  p.drawPixmap(m_effect_bounds.topLeft(),
923  *m_effect_pixmap, QRect(m_effect_bounds.topLeft(), dst_sz));
924  p.end();
925 
928 }
929 
931 {
932  static const int iyPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
933 
934  if (m_effect_current_frame == 0)
935  {
936  m_effect_bounds.setSize(size());
937  m_effect_i = 0;
938  }
939 
940  if (iyPos[m_effect_i] < 0)
941  {
943  m_effect_running = false;
944  update();
945  return;
946  }
947 
948  QPainter p(this);
949  for (int y = iyPos[m_effect_i]; y < m_effect_bounds.height(); y += 8)
950  {
951  p.drawPixmap(QPoint(0, y), *m_effect_pixmap,
952  QRect(0, y, m_effect_bounds.width(), 1));
953  }
954  p.end();
955 
956  m_effect_i++;
957 
958  if (iyPos[m_effect_i] >= 0)
959  {
962  }
963  else
964  {
966  m_effect_running = false;
967  update();
968  return;
969  }
970 }
971 
973 {
974  static const int ixPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
975 
976  if (m_effect_current_frame == 0)
977  {
978  m_effect_bounds.setSize(size());
979  m_effect_i = 0;
980  }
981 
982  if (ixPos[m_effect_i] < 0)
983  {
985  m_effect_running = false;
986  update();
987  return;
988  }
989 
990  QPainter p(this);
991  for (int x = ixPos[m_effect_i]; x < m_effect_bounds.width(); x += 8)
992  {
993  p.drawPixmap(QPoint(x, 0), *m_effect_pixmap,
994  QRect(x, 0, 1, m_effect_bounds.height()));
995  }
996  p.end();
997 
998  m_effect_i++;
999 
1000  if (ixPos[m_effect_i] >= 0)
1001  {
1004  }
1005  else
1006  {
1008  m_effect_running = false;
1009  update();
1010  return;
1011  }
1012 }
1013 
1015 {
1016  if (m_effect_current_frame == 0)
1017  {
1018  m_effect_bounds.setSize(size());
1019  m_effect_delta0 = QPoint(4, 16);
1020  m_effect_delta1 = QPoint(m_effect_bounds.width() / m_effect_delta0.x(), 0);
1022  }
1023 
1024  int x = 0;
1025  bool done = true;
1026  QPainter p(this);
1027  for (int i = 0; i < m_effect_delta1.x(); i++, x += m_effect_delta0.x())
1028  {
1029  int y = m_effect_meltdown_y_disp[i];
1030  if (y >= m_effect_bounds.height())
1031  continue;
1032 
1033  done = false;
1034  if ((random() & 0xF) < 6)
1035  continue;
1036 
1037  p.drawPixmap(QPoint(x, y), *m_effect_pixmap,
1038  QRect(x, y, m_effect_delta0.x(), m_effect_delta0.y()));
1039 
1041  }
1042  p.end();
1043 
1044  if (done)
1045  {
1047  m_effect_running = false;
1048  update();
1049  return;
1050  }
1051 
1054 }
1055 
1057 {
1058  if (m_effect_current_frame == 0)
1059  {
1060  m_effect_bounds.setSize(size());
1061  m_effect_delta1 = QPoint(m_effect_bounds.width() >> 1, m_effect_bounds.height() >> 1);
1062  m_effect_delta2_x = m_effect_delta1.x() * 0.01F;
1063  m_effect_delta2_y = m_effect_delta1.y() * 0.01F;
1064  m_effect_i = 0;
1065  m_effect_subtype = random() & 1;
1066  }
1067 
1068  m_effect_bounds.moveTopLeft(QPoint((int)(m_effect_delta2_x * m_effect_i),
1069  (int)(m_effect_delta2_y * m_effect_i)));
1070 
1072  {
1074  m_effect_running = false;
1075  update();
1076  return;
1077  }
1078 
1079  int x1 = m_effect_bounds.width() - m_effect_bounds.x();
1080  int y1 = m_effect_bounds.height() - m_effect_bounds.y();
1081  m_effect_i++;
1082 
1083  QPainter p(this);
1085  {
1086  // moving image edges
1087  p.drawPixmap(0, 0, *m_effect_pixmap,
1088  m_effect_delta1.x() - m_effect_bounds.x(),
1089  m_effect_delta1.y() - m_effect_bounds.y(),
1091  );
1092  p.drawPixmap(x1, 0, *m_effect_pixmap,
1095  );
1096  p.drawPixmap(0, y1, *m_effect_pixmap,
1099  );
1100  p.drawPixmap(x1, y1, *m_effect_pixmap,
1103  );
1104  }
1105  else
1106  {
1107  // fixed image edges
1108  p.drawPixmap( 0, 0, *m_effect_pixmap, 0, 0,
1109  m_effect_bounds.x(), m_effect_bounds.y());
1110  p.drawPixmap(x1, 0, *m_effect_pixmap, x1, 0,
1111  m_effect_bounds.x(), m_effect_bounds.y());
1112  p.drawPixmap( 0, y1, *m_effect_pixmap, 0, y1,
1113  m_effect_bounds.x(), m_effect_bounds.y());
1114  p.drawPixmap(x1, y1, *m_effect_pixmap, x1, y1,
1115  m_effect_bounds.x(), m_effect_bounds.y());
1116  }
1117  p.end();
1118 
1121 }
1122 
1124 {
1125  int i;
1126  float alpha;
1127 
1128  if (m_effect_current_frame == 0)
1129  {
1130  StartPainter();
1131  m_effect_bounds = QRect(width(), height() >> 1,
1132  width(), height());
1133 
1135  0, m_effect_bounds.width() >> 1, m_effect_bounds.height() >> 1);
1137  3, m_effect_bounds.width() >> 1, m_effect_bounds.height() >> 1);
1138 
1139  m_effect_delta2_y = sqrtf(sq(m_effect_bounds.width()) * 1.0F +
1140  sq(m_effect_bounds.height()) * 0.5F);
1141  m_effect_i = (random() & 0xf) + 2;
1145  m_effect_delta2_x = M_PI / 32; // divisor must be powers of 8
1146  }
1147 
1148  if (m_effect_alpha < 0)
1149  {
1150  m_effect_painter->end();
1151 
1153  m_effect_running = false;
1154  update();
1155  return;
1156  }
1157 
1158  for (alpha = m_effect_alpha, i = m_effect_i; i >= 0;
1160  {
1161  int x = (m_effect_bounds.width() >> 1) + (int)(m_effect_delta2_y * cos(-alpha));
1162  int y = (m_effect_bounds.height() >> 1) + (int)(m_effect_delta2_y * sin(-alpha));
1163 
1164  m_effect_bounds.moveTopLeft(
1165  QPoint((m_effect_bounds.width() >> 1) +
1166  (int)(m_effect_delta2_y * cos(-alpha + m_effect_delta2_x)),
1167  (m_effect_bounds.height() >> 1) +
1168  (int)(m_effect_delta2_y * sin(-alpha + m_effect_delta2_x))));
1169 
1170  m_effect_milti_circle_out_points.setPoint(1, x, y);
1172 
1174  }
1175 
1177 
1180 }
1181 
1183 {
1184  if (m_effect_current_frame == 0)
1185  {
1186  StartPainter();
1187  m_effect_delta0 = QPoint(width() >> 3, 0);
1188  m_effect_delta1 = QPoint(width() >> 3, height() >> 3);
1189  m_effect_i = 0;
1190  m_effect_j = 16 * 16;
1191  m_effect_bounds = QRect(QPoint(0,0), size());
1192  m_effect_spiral_tmp0 = QPoint(0, m_effect_delta1.y());
1193  m_effect_spiral_tmp1 = QPoint(m_effect_bounds.width() - m_effect_delta1.x(),
1194  m_effect_bounds.height() - m_effect_delta1.y());
1195  }
1196 
1197  if (m_effect_i == 0 && m_effect_spiral_tmp0.x() >= m_effect_spiral_tmp1.x())
1198  {
1199  m_effect_painter->end();
1200 
1202  m_effect_running = false;
1203  update();
1204  return;
1205  }
1206 
1207  if (m_effect_i == 0 && m_effect_bounds.x() >= m_effect_spiral_tmp1.x())
1208  {
1209  // switch to: down on right side
1210  m_effect_i = 1;
1211  m_effect_delta0 = QPoint(0, m_effect_delta1.y());
1213  }
1214  else if (m_effect_i == 1 && m_effect_bounds.y() >= m_effect_spiral_tmp1.y())
1215  {
1216  // switch to: right to left on bottom side
1217  m_effect_i = 2;
1218  m_effect_delta0 = QPoint(-m_effect_delta1.x(), 0);
1220  }
1221  else if (m_effect_i == 2 && m_effect_bounds.x() <= m_effect_spiral_tmp0.x())
1222  {
1223  // switch to: up on left side
1224  m_effect_i = 3;
1225  m_effect_delta0 = QPoint(0, -m_effect_delta1.y());
1227  }
1228  else if (m_effect_i == 3 && m_effect_bounds.y() <= m_effect_spiral_tmp0.y())
1229  {
1230  // switch to: left to right on top side
1231  m_effect_i = 0;
1232  m_effect_delta0 = QPoint(m_effect_delta1.x(), 0);
1234  }
1235 
1236  QPainter p(this);
1237  p.drawPixmap(m_effect_bounds.x(), m_effect_bounds.y(), *m_effect_pixmap,
1239  m_effect_delta1.x(), m_effect_delta1.y());
1240  p.end();
1241 
1242  m_effect_bounds.moveTopLeft(m_effect_bounds.topLeft() + m_effect_delta0);
1243  m_effect_j--;
1244 
1247 }
1248 
1250 {
1251  if (m_effect_current_frame == 0)
1252  {
1253  StartPainter();
1254  m_effect_bounds = QRect(QPoint(width(), height() >> 1), size());
1255  m_effect_alpha = 2 * M_PI;
1256 
1257  m_effect_circle_out_points.setPoint(
1258  0, m_effect_bounds.width() >> 1, m_effect_bounds.height() >> 1);
1259  m_effect_circle_out_points.setPoint(
1260  3, m_effect_bounds.width() >> 1, m_effect_bounds.height() >> 1);
1261 
1262  m_effect_delta2_x = M_PI / 16; // divisor must be powers of 8
1263  m_effect_delta2_y = sqrtf(sq(m_effect_bounds.width()) * 1.0F +
1264  sq(m_effect_bounds.height()) * 0.5F);
1265  }
1266 
1267  if (m_effect_alpha < 0)
1268  {
1269  m_effect_painter->end();
1270 
1272  m_effect_running = false;
1273  update();
1274  return;
1275  }
1276 
1277  QPoint tmp = m_effect_bounds.topLeft();
1278 
1279  m_effect_bounds.moveTopLeft(
1280  QPoint((m_effect_bounds.width() >> 1) +
1281  (int)(m_effect_delta2_y * cos(m_effect_alpha)),
1282  (m_effect_bounds.height() >> 1) +
1283  (int)(m_effect_delta2_y * sin(m_effect_alpha))));
1284 
1286 
1287  m_effect_circle_out_points.setPoint(1, tmp);
1288  m_effect_circle_out_points.setPoint(2, m_effect_bounds.topLeft());
1289 
1291 
1294 }
1295 
1297 {
1298  int r;
1299 
1300  if (m_effect_current_frame == 0)
1301  {
1302  StartPainter();
1303  m_effect_alpha = M_PI * 2;
1304  m_effect_bounds.setSize(size());
1305  m_effect_i = 150;
1306  }
1307 
1308  if (m_effect_i <= 0)
1309  {
1310  m_effect_painter->end();
1311 
1313  m_effect_running = false;
1314  update();
1315  return;
1316  }
1317 
1318  m_effect_bounds.setTopLeft(QPoint(random() % m_effect_bounds.width(),
1319  random() % m_effect_bounds.height()));
1320 
1321  r = (random() % 200) + 50;
1322 
1323  m_effect_painter->drawEllipse(m_effect_bounds.x() - r,
1324  m_effect_bounds.y() - r, r, r);
1325  m_effect_i--;
1326 
1329 }
1330 
1332 {
1333  int w, h, fact, sz;
1334 
1335  fact = (random() % 3) + 1;
1336 
1337  w = width() >> fact;
1338  h = height() >> fact;
1339  sz = 1 << fact;
1340 
1341  QPainter p(this);
1342  for (int i = (w * h) << 1; i > 0; i--)
1343  {
1344  int x = (random() % w) << fact;
1345  int y = (random() % h) << fact;
1346  p.drawPixmap(QPoint(x, y), *m_effect_pixmap, QRect(x, y, sz, sz));
1347  }
1348  p.end();
1349 
1351  m_effect_running = false;
1352  update();
1353 }
1354 
1356 {
1357  bool wasMovie = false, isMovie = false;
1358 
1359  if (m_caption_timer->isActive())
1360  {
1361  m_caption_timer->stop();
1362  }
1363 
1364  if (m_effect_method.isEmpty())
1365  {
1366  LOG(VB_GENERAL, LOG_ERR, LOC + "No transition method");
1367  return;
1368  }
1369 
1370  if (!m_effect_running)
1371  {
1373  {
1374  // wffect was running and is complete now
1375  // run timer while showing current image
1378  }
1379  else
1380  {
1381  // timed out after showing current image
1382  // load next image and start effect
1383  if (m_slideshow_running)
1384  {
1385  if (m_effect_random)
1387 
1388  DisplayNext(false, false);
1389 
1390  wasMovie = m_movieState > 0;
1391  Load();
1392  isMovie = m_movieState > 0;
1393  // If transitioning to/from a movie, don't do an effect,
1394  // and shorten timeout
1395  if (wasMovie || isMovie)
1396  {
1398  }
1399  else
1400  {
1402  m_effect_running = true;
1405  }
1406  }
1407  m_info_show_short = false;
1408  }
1409  }
1410 
1411  update();
1412 
1413  if (m_slideshow_running)
1414  {
1415  m_slideshow_timer->stop();
1416  m_slideshow_timer->setSingleShot(true);
1418 
1419  // If transitioning to/from a movie, no effect is running so
1420  // next timeout should trigger proper immage delay.
1421  if (wasMovie || isMovie)
1422  {
1424  }
1425  }
1426 }
1427 
1429 {
1430  m_caption_timer->stop();
1431  m_caption_remove = true;
1432  update();
1433 }
static const int kSweepRightToLeft
Definition: singleview.h:54
QPixmap * m_info_pixmap
Definition: singleview.h:114
QString GetCaption(void) const
Definition: thumbview.h:55
void EffectChessboard(void)
Definition: singleview.cpp:772
void GetScreenShot(QImage &image, const ThumbItem *item)
Definition: imageview.cpp:248
static const int kIncomingEdgesMoving
Definition: singleview.h:60
float m_zoom
Definition: imageview.h:99
int m_pos
Definition: imageview.h:96
void RunEffect(const QString &effect) override
Definition: singleview.cpp:701
QPolygon m_effect_circle_out_points
Definition: singleview.h:143
int m_screenwidth
Definition: mythdialogs.h:92
float m_effect_delta2_y
Definition: singleview.h:134
float m_hmult
Definition: imageview.h:95
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
void paintEvent(QPaintEvent *e) override
Definition: singleview.cpp:150
int m_caption_show
Definition: singleview.h:117
void DisableScreensaver(void)
static const int kSweepLeftToRight
Definition: singleview.h:55
void SetZoom(float zoom) override
Definition: singleview.cpp:639
void SaveSetting(const QString &key, int newValue)
static void PlayVideo(const QString &filename)
bool m_info_show_short
Definition: imageview.h:102
T sq(T val)
Definition: singleview.cpp:47
bool HasCaption(void) const
Definition: thumbview.h:54
int m_movieState
Definition: imageview.h:98
int m_slideshow_frame_delay_state
Definition: imageview.h:108
void DisplayPrev(bool reset, bool loadImage) override
Definition: singleview.cpp:553
bool m_caption_remove
Definition: singleview.h:118
QString GetDescription(const QString &status, const QSize &sz, int angle) const
Definition: thumbview.cpp:112
float m_effect_multi_circle_out_delta_alpha
Definition: singleview.h:141
int m_effect_j
misc effects iterator
Definition: singleview.h:131
ThumbItem * getCurrentItem() const
Definition: imageview.cpp:292
void keyPressEvent(QKeyEvent *e) override
Definition: singleview.cpp:305
SingleView(const ThumbList &itemList, int *pos, int slideShow, int sortorder, MythMainWindow *parent, const char *name="SingleView")
Definition: singleview.cpp:49
int m_slideshow_frame_delay
Definition: imageview.h:107
void EffectGrowing(void)
Definition: singleview.cpp:894
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void SetPixmap(QPixmap *pixmap)
Definition: thumbview.cpp:74
void EffectMultiCircleOut(void)
void setNoErase(void)
QList< ThumbItem * > ThumbList
Definition: thumbview.h:78
int matrix[4][2]
void UpdateLCD(const ThumbItem *item)
Definition: imageview.cpp:213
static guint32 * tmp
Definition: goom_core.c:35
int m_screenheight
Definition: mythdialogs.h:93
void CheckPosition(void)
Definition: singleview.cpp:512
void EffectVertLines(void)
Definition: singleview.cpp:972
void EffectNoise(void)
unsigned char r
Definition: ParseText.cpp:329
QString GetDescriptionStatus(void) const
Definition: imageview.cpp:240
QMap< QString, QString > m_effect_map
Definition: imageview.h:116
static bool IsMovie(const QString &filePath)
int m_effect_subtype
Definition: singleview.h:126
ThumbItem * retreatItem()
Definition: imageview.cpp:305
void EffectHorizLines(void)
Definition: singleview.cpp:930
static const int kSweepBottomToTop
Definition: singleview.h:56
long GetRotationAngle(void)
Definition: thumbview.cpp:80
void Load(void) override
Definition: singleview.cpp:582
QTimer * m_caption_timer
Definition: singleview.h:121
int m_effect_current_frame
Definition: imageview.h:114
virtual QString GetRandomEffect(void) const
Definition: imageview.cpp:203
static QPixmap * CreateBackground(const QSize &sz)
Definition: singleview.cpp:668
void EffectSpiralIn(void)
float m_effect_delta2_x
Definition: singleview.h:133
bool m_effect_random
Definition: imageview.h:117
static bool Delete(const QFileInfo &file)
static QSize ScaleToDest(const QSize &src, const QSize &dest, ScaleMax scaleMax)
QPixmap * m_caption_pixmap
Definition: singleview.h:119
QString GetSetting(const QString &key, const QString &defaultval="")
unsigned char t
Definition: ParseText.cpp:329
virtual void reject()
QPoint m_effect_spiral_tmp1
Definition: singleview.h:139
QString m_effect_method
Definition: imageview.h:115
virtual void done(int)
#define LOC
Definition: singleview.cpp:45
void Rotate(int angle) override
Definition: singleview.cpp:618
void CaptionTimeout(void)
void EffectNone(void)
Definition: singleview.cpp:765
void EffectMeltdown(void)
void EffectSweep(void)
Definition: singleview.cpp:822
const char * name
Definition: ParseText.cpp:328
QTimer * m_slideshow_timer
Definition: imageview.h:109
QPixmap * m_caption_restore_pixmap
Definition: singleview.h:120
MythUIHelper * GetMythUI()
vector< int > m_effect_meltdown_y_disp
Definition: singleview.h:140
bool m_effect_running
Definition: imageview.h:113
Base dialog for most dialogs in MythTV using the old UI.
Definition: mythdialogs.h:40
ScaleMax
Definition: galleryutil.h:28
float m_wmult
Definition: imageview.h:94
MythMainWindow * GetMythMainWindow(void)
QPainter * m_effect_painter
Definition: singleview.h:125
void EffectCircleOut(void)
#define M_PI
Definition: goom_tools.h:5
QString GetPath(void) const
Definition: thumbview.h:59
void PauseIdleTimer(bool pause)
void RestoreScreensaver(void)
int GetNumSetting(const QString &key, int defaultval=0)
QRect m_effect_bounds
effect image bounds
Definition: singleview.h:127
float m_effect_alpha
Definition: singleview.h:135
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QPoint m_effect_delta0
misc effects delta
Definition: singleview.h:128
void InitCaption(bool get_caption)
Definition: thumbview.cpp:44
QPoint m_effect_delta1
misc effects delta
Definition: singleview.h:129
void SetRotationAngle(int angle)
Definition: thumbview.cpp:58
ScaleMax m_scaleMax
Definition: singleview.h:111
QPixmap * m_effect_pixmap
Definition: singleview.h:124
void SetPixmap(QPixmap *)
Definition: singleview.cpp:658
void EffectIncomingEdges(void)
void keyPressEvent(QKeyEvent *e) override
void CreateEffectPixmap(void)
Definition: singleview.cpp:748
static long int random(void)
Definition: compat.h:149
QPoint m_effect_spiral_tmp0
Definition: singleview.h:138
QPolygon m_effect_milti_circle_out_points
Definition: singleview.h:142
QPixmap * m_pixmap
Definition: singleview.h:107
void SlideTimeout(void)
void EffectBlobs(void)
static const int kSweepTopToBottom
Definition: singleview.h:57
int m_effect_i
misc effects iterator
Definition: singleview.h:130
ThumbItem * advanceItem()
Definition: imageview.cpp:298
void RegisterEffects(void) override
Definition: singleview.cpp:684
QImage m_image
Definition: singleview.h:108
void DisplayNext(bool reset, bool loadImage) override
Definition: singleview.cpp:520
bool m_slideshow_running
Definition: imageview.h:105
void StartPainter(void)
Definition: singleview.cpp:731
QPoint m_source_loc
Definition: singleview.h:110
static int x1
Definition: mythsocket.cpp:60
bool m_info_show
Definition: imageview.h:101
int m_effect_framerate
timeout between effects
Definition: singleview.h:132