MythTV  master
mythuitype.cpp
Go to the documentation of this file.
1 
2 // Own header
3 #include "mythuitype.h"
4 
5 // QT headers
6 #include <QDomDocument>
7 #include <QEvent>
8 #include <QKeyEvent>
9 #include <utility>
10 
11 // XML headers
12 #include "xmlparsebase.h"
13 
14 // Mythbase headers
15 #include "mythlogging.h"
16 #include "mythmedia.h"
17 
18 // MythUI headers
19 #include "mythgesture.h"
20 #include "mythimage.h"
21 #include "mythpainter.h"
22 #include "mythmainwindow.h"
23 #include "mythfontproperties.h"
24 #include "mythuitext.h"
25 #include "mythuiimage.h"
26 #include "mythuibutton.h"
27 #include "mythuicheckbox.h"
28 #include "mythuibuttonlist.h"
29 #include "mythuitextedit.h"
30 #include "mythuiprogressbar.h"
31 #include "mythuispinbox.h"
32 #include "mythuigroup.h"
33 #include "mythgesture.h"
34 
35 #ifdef _MSC_VER
36 # include "compat.h" // random
37 #endif
38 
39 #define LOC QString("MythUIType: ")
40 
41 MythUIType::MythUIType(QObject *parent, const QString &name)
42  : QObject(parent)
43 {
44  setObjectName(name);
45 
46  if (parent)
47  {
48  m_Parent = dynamic_cast<MythUIType *>(parent);
49 
50  if (m_Parent)
51  m_Parent->AddChild(this);
52  }
53 
54  m_Fonts = new FontMap();
55 
56  m_BorderColor = QColor(random() % 255, random() % 255, random() % 255);
57 }
58 
60 {
61  delete m_Fonts;
62  qDeleteAll(m_animations);
63 }
64 
70 {
71  // Reset all children
72  QMutableListIterator<MythUIType *> it(m_ChildrenList);
73 
74  while (it.hasNext())
75  {
76  it.next();
77  MythUIType *type = it.value();
78  type->Reset();
79  }
80 }
81 
86 {
87  if (!child)
88  return;
89 
90  m_ChildrenList.push_back(child);
91 }
92 
93 static QObject *qChildHelper(const char *objName, const char *inheritsClass,
94  bool recursiveSearch, const QObjectList &children)
95 {
96  if (children.isEmpty())
97  return nullptr;
98 
99  bool onlyWidgets = (inheritsClass
100  && qstrcmp(inheritsClass, "QWidget") == 0);
101  const QLatin1String oName(objName);
102 
103  foreach (auto obj, children)
104  {
105  if (onlyWidgets)
106  {
107  if (obj->isWidgetType() && (!objName || obj->objectName() == oName))
108  return obj;
109  }
110  else if ((!inheritsClass || obj->inherits(inheritsClass))
111  && (!objName || obj->objectName() == oName))
112  return obj;
113 
114  if (recursiveSearch && (dynamic_cast<MythUIGroup *>(obj) != nullptr)
115  && (obj = qChildHelper(objName, inheritsClass,
116  recursiveSearch,
117  obj->children())))
118  return obj;
119  }
120 
121  return nullptr;
122 }
123 
130 MythUIType *MythUIType::GetChild(const QString &name) const
131 {
132  QObject *ret = qChildHelper(name.toLatin1().constData(), nullptr, true, children());
133 
134  if (ret)
135  return dynamic_cast<MythUIType *>(ret);
136 
137  return nullptr;
138 }
139 
145 void MythUIType::DeleteChild(const QString &name)
146 {
147  QMutableListIterator<MythUIType *> it(m_ChildrenList);
148 
149  while (it.hasNext())
150  {
151  it.next();
152  MythUIType *type = it.value();
153 
154  if (type->objectName() == name)
155  {
156  delete type;
157  it.remove();
158  return;
159  }
160  }
161 }
162 
170 {
171  if (!child)
172  return;
173 
174  QMutableListIterator<MythUIType *> it(m_ChildrenList);
175 
176  while (it.hasNext())
177  {
178  it.next();
179  MythUIType *type = it.value();
180 
181  if (type == child)
182  {
183  delete type;
184  it.remove();
185  child = nullptr;
186  return;
187  }
188  }
189 }
190 
194 QList<MythUIType *> *MythUIType::GetAllChildren(void)
195 {
196  return &m_ChildrenList;
197 }
198 
203 {
204  QList<MythUIType *>::iterator it;
205 
206  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
207  if (*it)
208  delete *it;
209 
210  m_ChildrenList.clear();
211 }
212 
221 MythUIType *MythUIType::GetChildAt(const QPoint &p, bool recursive,
222  bool focusable) const
223 {
224  if (GetArea().contains(p))
225  {
226  if (!IsVisible() || !IsEnabled())
227  return nullptr;
228 
229  if (m_ChildrenList.isEmpty())
230  return nullptr;
231 
232  /* check all children */
233  QList<MythUIType *>::const_iterator it;
234 
235  for (it = m_ChildrenList.end() - 1; it != m_ChildrenList.begin() - 1; --it)
236  {
237  if (!(*it))
238  continue;
239 
240  // If this point doesn't fall within the child's area then move on
241  // This requires that the area is actually accurate and in some
242  // cases this still isn't true
243  if (!(*it)->GetArea().contains(p - GetArea().topLeft()))
244  continue;
245 
246 
247  MythUIType *child = *it;
248 
249  if (recursive && (focusable && !child->CanTakeFocus()))
250  child = child->GetChildAt(p - GetArea().topLeft(), recursive,
251  focusable);
252 
253  if (child)
254  {
255  // NOTE: Assumes no selectible ui type will contain another
256  // selectible ui type.
257  if (focusable && !child->CanTakeFocus())
258  continue;
259 
260  return child;
261  }
262  }
263  }
264 
265  return nullptr;
266 }
267 
269 {
270  foreach (MythUIAnimation* animation, m_animations)
271  if (animation->GetTrigger() == trigger)
272  animation->Activate();
273 
274  foreach (MythUIType* uiType, m_ChildrenList)
275  uiType->ActivateAnimations(trigger);
276 }
277 
278 bool MythUIType::NeedsRedraw(void) const
279 {
280  return m_NeedsRedraw;
281 }
282 
284 {
285  m_NeedsRedraw = false;
286 
287  QList<MythUIType *>::Iterator it;
288 
289  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
290  (*it)->ResetNeedsRedraw();
291 }
292 
294 {
295  if (m_Area.width() == 0 || m_Area.height() == 0)
296  return;
297 
298  m_NeedsRedraw = true;
299 
300  if (m_DirtyRegion.isEmpty())
301  m_DirtyRegion = QRegion(m_Area.toQRect());
302  else
303  m_DirtyRegion = m_DirtyRegion.united(QRegion(m_Area.toQRect()));
304 
305  if (m_Parent)
307 }
308 
310 {
311  QRegion childRegion = child->GetDirtyArea();
312 
313  if (childRegion.isEmpty())
314  return;
315 
316  childRegion.translate(m_Area.x(), m_Area.y());
317 
318  childRegion = childRegion.intersected(m_Area.toQRect());
319 
320  m_NeedsRedraw = true;
321 
322  if (m_DirtyRegion.isEmpty())
323  m_DirtyRegion = childRegion;
324  else
325  m_DirtyRegion = m_DirtyRegion.united(childRegion);
326 
327  if (m_Parent)
329 }
330 
334 bool MythUIType::CanTakeFocus(void) const
335 {
336  return m_CanHaveFocus;
337 }
338 
343 {
344  m_CanHaveFocus = set;
345 }
346 
353 {
354  if (!GetPainter()->SupportsAnimation())
355  return;
356 
357  if (!m_Moving)
358  return;
359 
360  QPoint curXY = m_Area.topLeft().toQPoint();
362 
363  int xdir = m_XYDestination.x() - curXY.x();
364  int ydir = m_XYDestination.y() - curXY.y();
365 
366  curXY.setX(curXY.x() + m_XYSpeed.x());
367  curXY.setY(curXY.y() + m_XYSpeed.y());
368 
369  if ((xdir > 0 && curXY.x() >= m_XYDestination.x()) ||
370  (xdir < 0 && curXY.x() <= m_XYDestination.x()) ||
371  (xdir == 0))
372  {
373  m_XYSpeed.setX(0);
374  }
375 
376  if ((ydir > 0 && curXY.y() >= m_XYDestination.y()) ||
377  (ydir <= 0 && curXY.y() <= m_XYDestination.y()) ||
378  (ydir == 0))
379  {
380  m_XYSpeed.setY(0);
381  }
382 
383  SetRedraw();
384 
385  if (m_XYSpeed.x() == 0 && m_XYSpeed.y() == 0)
386  {
387  m_Moving = false;
388  emit FinishedMoving();
389  }
390 
391  m_Area.moveTopLeft(curXY);
392 }
393 
400 {
401  if (!GetPainter()->SupportsAlpha() ||
402  !GetPainter()->SupportsAnimation())
403  return;
404 
405  if (m_AlphaChangeMode == 0)
406  return;
407 
409 
412 
415 
416  // Reached limits so change direction
418  {
419  if (m_AlphaChangeMode == 2)
420  {
421  m_AlphaChange *= -1;
422  }
423  else
424  {
425  m_AlphaChangeMode = 0;
426  m_AlphaChange = 0;
427  emit FinishedFading();
428  }
429  }
430 
431  SetRedraw();
432 }
433 
441 {
442  if (!m_Visible || m_Vanished)
443  return;
444 
447 
448  QList<MythUIAnimation*>::Iterator i;
449  for (i = m_animations.begin(); i != m_animations.end(); ++i)
450  (*i)->IncrementCurrentTime();
451 
452  QList<MythUIType *>::Iterator it;
453 
454  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
455  (*it)->Pulse();
456 }
457 
458 int MythUIType::CalcAlpha(int alphamod)
459 {
460  return (int)(m_Effects.m_alpha * (alphamod / 255.0));
461 }
462 
463 void MythUIType::DrawSelf(MythPainter * /*p*/, int /*xoffset*/, int /*yoffset*/,
464  int /*alphaMod*/, QRect /*clipRect*/)
465 {
466 }
467 
468 void MythUIType::Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod,
469  QRect clipRect)
470 {
471  // NB m_DirtyRegion may be extended by HandleMovementPulse, SetRedraw
472  // or SetChildNeedsRedraw etc _AFTER_ GetDirtyArea is called.
473  // So clipRect may not include the whole of m_DirtyRegion
474  m_DirtyRegion -= QRegion(clipRect); // NB Qt >= 4.2
475 
476  if (!m_Visible || m_Vanished)
477  return;
478 
479  QRect realArea = m_Area.toQRect();
480  realArea.translate(xoffset, yoffset);
481 
482  if (!realArea.intersects(clipRect))
483  return;
484 
485  p->PushTransformation(m_Effects, m_Effects.GetCentre(m_Area, xoffset, yoffset));
486 
487  DrawSelf(p, xoffset, yoffset, alphaMod, clipRect);
488 
489  QList<MythUIType *>::Iterator it;
490 
491  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
492  {
493  (*it)->Draw(p, xoffset + m_Area.x(), yoffset + m_Area.y(),
494  CalcAlpha(alphaMod), clipRect);
495  }
496 
497  if (p->ShowBorders())
498  {
499  static const QBrush kNullBrush(Qt::NoBrush);
500  QPen pen(m_BorderColor);
501  pen.setWidth(1);
502  p->DrawRect(realArea, kNullBrush, pen, 255);
503 
504  if (p->ShowTypeNames())
505  {
506  MythFontProperties font;
507  font.SetFace(QFont("Droid Sans"));
508  font.SetColor(m_BorderColor);
509  font.SetPointSize(8);
510  p->DrawText(realArea, objectName(), 0, font, 255, realArea);
511  }
512  }
513 
514  p->PopTransformation();
515 }
516 
517 void MythUIType::SetPosition(int x, int y)
518 {
519  SetPosition(MythPoint(x, y));
520 }
521 
523 {
524  MythPoint pos(point);
525 
526  if (m_Parent)
528  else
529  pos.CalculatePoint(GetMythMainWindow()->GetUIScreenRect());
530 
531  if (m_Area.topLeft() == pos)
532  return;
533 
534  m_DirtyRegion = QRegion(m_Area.toQRect());
535 
536  m_Area.moveTopLeft(pos);
537 
538  RecalculateArea(false);
539 
540  SetRedraw();
541 }
542 
544 {
545  return m_Area.topLeft();
546 }
547 
548 void MythUIType::SetSize(const QSize &size)
549 {
550  if (size == m_Area.size())
551  return;
552 
553  m_DirtyRegion = QRegion(m_Area.toQRect());
554 
555  m_Area.setSize(size);
556  RecalculateArea();
557 
558  if (m_Parent)
560 
561  SetRedraw();
562 }
563 
569 void MythUIType::SetMinSize(const MythPoint &minsize)
570 {
571  MythPoint point(minsize);
572 
573  if (m_Parent)
575 
576  m_MinSize = point;
577 
578  SetRedraw();
579 }
580 
581 QSize MythUIType::GetMinSize(void) const
582 {
583  if (!m_MinSize.isValid())
584  return m_Area.size();
585 
586  return {m_MinSize.x(), m_MinSize.y()};
587 }
588 
589 void MythUIType::SetArea(const MythRect &rect)
590 {
591  if (rect == m_Area)
592  return;
593 
594  m_DirtyRegion = QRegion(m_Area.toQRect());
595 
596  m_Area = rect;
597  RecalculateArea();
598 
599  if (m_Parent)
601 
602  SetRedraw();
603 }
604 
608 void MythUIType::AdjustMinArea(int delta_x, int delta_y,
609  int delta_w, int delta_h)
610 {
611  // If a minsize is not set, don't use MinArea
612  if (!m_MinSize.isValid())
613  return;
614 
615  // Delta's are negative values; knock down the area
616  QRect bounded(m_Area.x() - delta_x,
617  m_Area.y() - delta_y,
618  m_Area.width() + delta_w,
619  m_Area.height() + delta_h);
620 
621  // Make sure we have not violated the min size
622  if (!bounded.isNull() || !m_Vanish)
623  {
624  QPoint center = bounded.center();
625 
626  if (bounded.isNull())
627  bounded.setSize(GetMinSize());
628  else
629  bounded.setSize(bounded.size().expandedTo(GetMinSize()));
630 
631  bounded.moveCenter(center);
632  }
633 
634  if (bounded.x() + bounded.width() > m_Area.x() + m_Area.width())
635  bounded.moveRight(m_Area.x() + m_Area.width());
636  if (bounded.y() + bounded.height() > m_Area.y() + m_Area.height())
637  bounded.moveBottom(m_Area.y() + m_Area.height());
638  if (bounded.x() < m_Area.x())
639  {
640  bounded.moveLeft(m_Area.x());
641  if (bounded.width() > m_Area.width())
642  bounded.setWidth(m_Area.width());
643  }
644  if (bounded.y() < m_Area.y())
645  {
646  bounded.moveTop(m_Area.y());
647  if (bounded.height() > m_Area.height())
648  bounded.setHeight(m_Area.height());
649  }
650 
651  m_MinArea = bounded;
652  m_Vanished = false;
653 
654  QList<MythUIType *>::iterator it;
655 
656  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
657  {
658  if (!(*it)->m_Initiator)
659  (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h);
660  }
661 }
662 
664 {
665  if (!m_MinSize.isValid() || !m_Vanish)
666  return;
667 
668  m_MinArea.moveLeft(0);
669  m_MinArea.moveTop(0);
670  m_MinArea.setWidth(0);
671  m_MinArea.setHeight(0);
672  m_Vanished = true;
673 
674  QList<MythUIType *>::iterator it;
675 
676  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
677  {
678  if (!(*it)->m_Initiator)
679  (*it)->VanishSibling();
680  }
681 }
682 
686 void MythUIType::SetMinAreaParent(MythRect actual_area, MythRect allowed_area,
687  MythUIType *calling_child)
688 {
689  int delta_x = 0;
690  int delta_y = 0;
691  int delta_w = 0;
692  int delta_h = 0;
693  MythRect area;
694 
695  // If a minsize is not set, don't use MinArea
696  if (!m_MinSize.isValid())
697  return;
698 
699  if (calling_child->m_Vanished)
700  {
701  actual_area.moveLeft(0);
702  actual_area.moveTop(0);
703  allowed_area.moveLeft(0);
704  allowed_area.moveTop(0);
705  }
706 
707  actual_area.translate(m_Area.x(), m_Area.y());
708  allowed_area.translate(m_Area.x(), m_Area.y());
709 
710  QList<MythUIType *>::iterator it;
711 
712  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
713  {
714  if (*it == calling_child || !(*it)->m_Initiator)
715  continue;
716 
717  if (!(*it)->m_Vanished)
718  {
719  // Find union of area(s)
720  area = (*it)->GetArea();
721  area.translate(m_Area.x(), m_Area.y());
722  actual_area = actual_area.united(area);
723 
724  area = (*it)->m_Area;
725  area.translate(m_Area.x(), m_Area.y());
726  allowed_area = allowed_area.united(area);
727  }
728  }
729 
730  // Make sure it is not larger than the area allowed
731  actual_area = actual_area.intersected(m_Area);
732  allowed_area = allowed_area.intersected(m_Area);
733 
734  if (m_Vanish && actual_area.size().isNull())
735  {
736  m_Vanished = true;
737  }
738  else
739  {
740  if (calling_child->m_Vanished)
741  {
742  delta_x = m_Area.x() - actual_area.x();
743  delta_y = m_Area.y() - actual_area.y();
744  delta_w = actual_area.width() - m_Area.width();
745  delta_h = actual_area.height() - m_Area.height();
746  }
747  else
748  {
749  delta_x = allowed_area.x() - actual_area.x();
750  delta_y = allowed_area.y() - actual_area.y();
751  delta_w = actual_area.width() - allowed_area.width();
752  delta_h = actual_area.height() - allowed_area.height();
753  }
754 
755  m_Vanished = false;
756  }
757 
758  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
759  {
760  if (*it == calling_child)
761  continue;
762 
763  if (!(*it)->m_Initiator)
764  {
765  if (m_Vanished)
766  (*it)->VanishSibling();
767  else
768  (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h);
769  }
770 
771  area = (*it)->GetArea();
772  area.translate(m_Area.topLeft());
773  actual_area = actual_area.united(area);
774  }
775 
776  if (m_Vanished)
777  {
778  m_MinArea.setRect(0, 0, 0, 0);
779  actual_area.setRect(0, 0, 0, 0);
780  }
781  else
782  {
783  QSize bound(actual_area.width(), actual_area.height());
784 
785  bound = bound.expandedTo(GetMinSize());
786  m_MinArea.setRect(actual_area.x(),
787  actual_area.y(),
788  actual_area.x() + bound.width(),
789  actual_area.y() + bound.height());
790  }
791 
792  if (m_Parent)
793  m_Parent->SetMinAreaParent(actual_area, m_Area, this);
794 }
795 
800 {
801  // If a minsize is not set, don't use MinArea
802  if (!m_Initiator || !m_MinSize.isValid())
803  return;
804 
805  QRect bounded(rect);
806  bool vanish = (m_Vanish && rect.isNull());
807 
808  if (vanish)
809  {
810  bounded.moveLeft(0);
811  bounded.moveTop(0);
812  }
813  else
814  {
815  QPoint center = bounded.center();
816 
817  if (bounded.isNull())
818  bounded.setSize(GetMinSize());
819  else
820  bounded.setSize(bounded.size().expandedTo(GetMinSize()));
821 
822  bounded.moveCenter(center);
823  if (bounded.x() + bounded.width() > m_Area.x() + m_Area.width())
824  bounded.moveRight(m_Area.x() + m_Area.width());
825  if (bounded.y() + bounded.height() > m_Area.y() + m_Area.height())
826  bounded.moveBottom(m_Area.y() + m_Area.height());
827  if (bounded.x() < m_Area.x())
828  {
829  bounded.moveLeft(m_Area.x());
830  if (bounded.width() > m_Area.width())
831  bounded.setWidth(m_Area.width());
832  }
833  if (bounded.y() < m_Area.y())
834  {
835  bounded.moveTop(m_Area.y());
836  if (bounded.height() > m_Area.height())
837  bounded.setHeight(m_Area.height());
838  }
839  }
840 
841  m_MinArea = bounded;
842  m_Vanished = vanish;
843 
844  if (m_Parent)
846 }
847 
849 {
850  QSize childSize = rect.size();
851  QSize size = m_Area.size();
852 
853  if (childSize == size)
854  return;
855 
856  SetSize(size.expandedTo(childSize));
857  SetRedraw();
858 }
859 
865 {
866  if (m_Vanished || m_MinArea.isValid())
867  return m_MinArea;
868 
869  return m_Area;
870 }
871 
873 {
874  return m_Area;
875 }
876 
877 QRegion MythUIType::GetDirtyArea(void) const
878 {
879  return m_DirtyRegion;
880 }
881 
882 bool MythUIType::IsVisible(bool recurse) const
883 {
884  if (recurse)
885  {
886  if (m_Parent && !m_Parent->IsVisible(recurse))
887  return false;
888  }
889 
890  return m_Visible;
891 }
892 
893 void MythUIType::MoveTo(QPoint destXY, QPoint speedXY)
894 {
895  if (!GetPainter()->SupportsAnimation())
896  return;
897 
898  if (destXY.x() == m_Area.x() && destXY.y() == m_Area.y())
899  return;
900 
901  m_Moving = true;
902 
903  m_XYDestination = destXY;
904  m_XYSpeed = speedXY;
905 }
906 
907 void MythUIType::AdjustAlpha(int mode, int alphachange, int minalpha,
908  int maxalpha)
909 {
910  if (!GetPainter()->SupportsAlpha())
911  return;
912 
913  m_AlphaChangeMode = mode;
914  m_AlphaChange = alphachange;
915  m_AlphaMin = minalpha;
916  m_AlphaMax = maxalpha;
917 
920 
923 }
924 
925 void MythUIType::SetAlpha(int newalpha)
926 {
927  if (m_Effects.m_alpha == newalpha)
928  return;
929 
930  m_Effects.m_alpha = newalpha;
931  SetRedraw();
932 }
933 
934 int MythUIType::GetAlpha(void) const
935 {
936  return m_Effects.m_alpha;
937 }
938 
940 {
941  m_Effects.m_centre = centre;
942 }
943 
944 void MythUIType::SetZoom(float zoom)
945 {
946  SetHorizontalZoom(zoom);
947  SetVerticalZoom(zoom);
948 }
949 
951 {
952  m_Effects.m_hzoom = zoom;
953  SetRedraw();
954 }
955 
957 {
958  m_Effects.m_vzoom = zoom;
959  SetRedraw();
960 }
961 
962 void MythUIType::SetAngle(float angle)
963 {
964  m_Effects.m_angle = angle;
965  SetRedraw();
966 }
967 
972 bool MythUIType::keyPressEvent(QKeyEvent * /*event*/)
973 {
974  return false;
975 }
976 
977 
978 void MythUIType::customEvent(QEvent *event)
979 {
980  QObject::customEvent(event);
981 }
982 
989 {
990  return false;
991 }
992 
998 {
999 }
1000 
1002 {
1003  if (!m_CanHaveFocus || !m_HasFocus)
1004  return;
1005 
1006  emit LosingFocus();
1007  m_HasFocus = false;
1008  Refresh();
1009 }
1010 
1012 {
1013  if (!m_CanHaveFocus || m_HasFocus)
1014  return false;
1015 
1016  m_HasFocus = true;
1017  Refresh();
1018  emit TakingFocus();
1019  return true;
1020 }
1021 
1023 {
1024 }
1025 
1027 {
1028  SetRedraw();
1029 }
1030 
1031 void MythUIType::UpdateDependState(MythUIType *dependee, bool isDefault)
1032 {
1033  bool visible = false;
1034 
1035  if (dependee)
1036  {
1037  bool reverse = m_ReverseDepend[dependee];
1038  visible = reverse ? !isDefault : isDefault;
1039  // NOLINTNEXTLINE(modernize-loop-convert)
1040  for (int i = 0; i < m_dependsValue.size(); i++)
1041  {
1042  if (m_dependsValue[i].first != dependee)
1043  continue;
1044  m_dependsValue[i].second = visible;
1045  break;
1046  }
1047  }
1048 
1049  if (!m_dependsValue.empty())
1050  visible = m_dependsValue[0].second;
1051  for (int i = 1; i < m_dependsValue.size(); i++)
1052  {
1053  bool v = m_dependsValue[i].second;
1054 
1055  if (((i-1) < m_dependOperator.size()) &&
1056  m_dependOperator[i-1] == 1)
1057  {
1058  // OR operator
1059  visible = visible && v;
1060  }
1061  else
1062  {
1063  // AND operator
1064  visible = visible || v;
1065  }
1066  }
1067 
1068  m_IsDependDefault = visible;
1069 
1071 }
1072 
1073 void MythUIType::UpdateDependState(bool isDefault)
1074 {
1075  auto *dependee = static_cast<MythUIType*>(sender());
1076 
1077  UpdateDependState(dependee, isDefault);
1078 }
1079 
1080 void MythUIType::SetVisible(bool visible)
1081 {
1082  if (visible == m_Visible)
1083  return;
1084 
1085  if (visible && m_IsDependDefault)
1086  return;
1087 
1088  m_Visible = visible;
1089  SetRedraw();
1090 
1091  if (m_Visible)
1092  emit Showing();
1093  else
1094  emit Hiding();
1095 }
1096 
1098 {
1099  m_IsDependDefault = isDefault;
1100 }
1101 
1102 void MythUIType::SetEnabled(bool enable)
1103 {
1104  if (m_Enabled != enable)
1105  m_Enabled = enable;
1106 
1107  if (enable)
1108  emit Enabling();
1109  else
1110  emit Disabling();
1111 }
1112 
1114 {
1115  SetVisible(false);
1116 }
1117 
1119 {
1120  SetVisible(true);
1121 }
1122 
1123 void MythUIType::AddFocusableChildrenToList(QMap<int, MythUIType *> &focusList)
1124 {
1125  if (m_CanHaveFocus)
1126  focusList.insertMulti(m_focusOrder, this);
1127 
1128  QList<MythUIType *>::Iterator it;
1129 
1130  for (it = m_ChildrenList.end() - 1; it != m_ChildrenList.begin() - 1; --it)
1131  (*it)->AddFocusableChildrenToList(focusList);
1132 }
1133 
1134 int MythUIType::NormX(const int width)
1135 {
1136  return GetMythMainWindow()->NormX(width);
1137 }
1138 
1139 int MythUIType::NormY(const int height)
1140 {
1141  return GetMythMainWindow()->NormY(height);
1142 }
1143 
1148 {
1149  m_xmlName = base->m_xmlName;
1150  m_xmlLocation = base->m_xmlLocation;
1151  m_Visible = base->m_Visible;
1152  m_Enabled = base->m_Enabled;
1154  m_focusOrder = base->m_focusOrder;
1155 
1156  m_Area = base->m_Area;
1157  RecalculateArea();
1158 
1160  m_MinSize = base->m_MinSize;
1161  m_Vanish = base->m_Vanish;
1162  m_Vanished = false;
1163  m_Effects = base->m_Effects;
1165  m_AlphaChange = base->m_AlphaChange;
1166  m_AlphaMin = base->m_AlphaMin;
1167  m_AlphaMax = base->m_AlphaMax;
1168 
1169  m_Moving = base->m_Moving;
1171  m_XYSpeed = base->m_XYSpeed;
1172  m_deferload = base->m_deferload;
1173 
1174  QList<MythUIAnimation*>::Iterator i;
1175  for (i = base->m_animations.begin(); i != base->m_animations.end(); ++i)
1176  {
1177  auto* animation = new MythUIAnimation(this);
1178  animation->CopyFrom(*i);
1179  m_animations.push_back(animation);
1180  }
1181 
1182  QList<MythUIType *>::Iterator it;
1183 
1184  for (it = base->m_ChildrenList.begin(); it != base->m_ChildrenList.end();
1185  ++it)
1186  {
1187  MythUIType *child = GetChild((*it)->objectName());
1188 
1189  if (child)
1190  child->CopyFrom(*it);
1191  else
1192  (*it)->CreateCopy(this);
1193  }
1194 
1195  m_dependsMap = base->m_dependsMap;
1196 
1197  SetMinArea(base->m_MinArea);
1198 }
1199 
1205 {
1206  // Calling CreateCopy on base type is not valid
1207 }
1208 
1214  const QString &filename, QDomElement &element, bool showWarnings)
1215 {
1216  //FIXME add movement etc.
1217 
1218  if (element.tagName() == "position")
1219  SetPosition(parsePoint(element));
1220  else if (element.tagName() == "area")
1221  {
1222  SetArea(parseRect(element));
1223  }
1224  else if (element.tagName() == "minsize")
1225  {
1226  // Use parsePoint so percentages can be used
1227  if (element.hasAttribute("initiator"))
1228  m_EnableInitiator = parseBool(element.attribute("initiator"));
1229 
1230  if (element.hasAttribute("vanish"))
1231  m_Vanish = parseBool(element.attribute("vanish"));
1232 
1233  SetMinSize(parsePoint(element));
1234  }
1235  else if (element.tagName() == "alpha")
1236  {
1237  m_Effects.m_alpha = getFirstText(element).toInt();
1238  m_AlphaChangeMode = 0;
1239  }
1240  else if (element.tagName() == "alphapulse")
1241  {
1242  m_AlphaChangeMode = 2;
1243  m_AlphaMin = element.attribute("min", "0").toInt();
1244  m_Effects.m_alpha = m_AlphaMax = element.attribute("max", "255").toInt();
1245 
1246  if (m_AlphaMax > 255)
1247  m_Effects.m_alpha = m_AlphaMax = 255;
1248 
1249  if (m_AlphaMin < 0)
1250  m_AlphaMin = 0;
1251 
1252  m_AlphaChange = element.attribute("change", "5").toInt();
1253  }
1254  else if (element.tagName() == "focusorder")
1255  {
1256  int order = getFirstText(element).toInt();
1257  SetFocusOrder(order);
1258  }
1259  else if (element.tagName() == "loadondemand")
1260  {
1261  SetDeferLoad(parseBool(element));
1262  }
1263  else if (element.tagName() == "helptext")
1264  {
1265  m_helptext = getFirstText(element);
1266  }
1267  else if (element.tagName() == "animation")
1268  {
1269  MythUIAnimation::ParseElement(element, this);
1270  }
1271  else {
1272  if (showWarnings) {
1273  VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
1274  QString("Unknown widget type '%1'").arg(element.tagName()));
1275  }
1276  return false;
1277  }
1278 
1279  return true;
1280 }
1281 
1290 {
1291 }
1292 
1293 MythFontProperties *MythUIType::GetFont(const QString &text) const
1294 {
1295  MythFontProperties *ret = m_Fonts->GetFont(text);
1296 
1297  if (!ret && m_Parent)
1298  return m_Parent->GetFont(text);
1299 
1300  return ret;
1301 }
1302 
1304 {
1305  return m_Fonts->AddFont(text, fontProp);
1306 }
1307 
1309 {
1310  if (m_Parent)
1312  else
1313  m_Area.CalculateArea(GetMythMainWindow()->GetUIScreenRect());
1314 
1315  if (recurse)
1316  {
1317  QList<MythUIType *>::iterator it;
1318 
1319  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
1320  {
1321  (*it)->RecalculateArea(recurse);
1322  }
1323  }
1324 }
1325 
1327 {
1328  m_focusOrder = order;
1329 }
1330 
1332 {
1333  if (!child)
1334  return false;
1335 
1336  int i = m_ChildrenList.indexOf(child);
1337 
1338  if (i != -1 || i != m_ChildrenList.size() - 1)
1339  {
1340  m_ChildrenList.removeAt(i);
1341  m_ChildrenList.append(child);
1342  child->SetRedraw();
1343  return true;
1344  }
1345 
1346  return false;
1347 }
1348 
1349 
1351 {
1352  if (m_Parent)
1353  {
1354  return m_Parent->MoveChildToTop(this);
1355  }
1356 
1357  return false;
1358 }
1359 
1360 bool MythUIType::IsDeferredLoading(bool recurse) const
1361 {
1362  if (m_deferload)
1363  return true;
1364 
1365  if (recurse && m_Parent)
1366  return m_Parent->IsDeferredLoading(recurse);
1367 
1368  return false;
1369 }
1370 
1377 {
1378  QList<MythUIType *>::Iterator it;
1379 
1380  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
1381  (*it)->LoadNow();
1382 }
1383 
1389 bool MythUIType::ContainsPoint(const QPoint &point) const
1390 {
1391  return m_Area.contains(point);
1392 }
1393 
1395 {
1396  if (m_Painter)
1397  return m_Painter;
1398 
1399  if (m_Parent)
1400  return m_Parent->GetPainter();
1401 
1402  return GetMythPainter();
1403 }
1404 
1405 void MythUIType::SetDependsMap(QMap<QString, QString> dependsMap)
1406 {
1407  m_dependsMap = std::move(dependsMap);
1408 }
1409 
1410 void MythUIType::SetReverseDependence(MythUIType *dependee, bool reverse)
1411 {
1412  m_ReverseDepend.insert(dependee, reverse);
1413 }
1414 
1416 {
1417  QMapIterator<QString, QString> it(m_dependsMap);
1418  while(it.hasNext())
1419  {
1420  it.next();
1421 
1422  // build list of operators and dependeees.
1423  QStringList dependees;
1424  QList<int> operators;
1425  QString name = it.value();
1426  QStringList tmp1 = name.split("&");
1427  for (int i = 0; i < tmp1.size(); i++)
1428  {
1429  QStringList tmp2 = tmp1[i].split("|");
1430 
1431  dependees.append(tmp2[0]);
1432  for (int j = 1; j < tmp2.size(); j++)
1433  {
1434  dependees.append(tmp2[j]);
1435  operators.append(1); // 1 is OR
1436  }
1437  operators.append(2); // 2 is AND
1438  }
1439 
1440  MythUIType *dependant = GetChild(it.key());
1441  if (dependant)
1442  {
1443  dependant->m_dependOperator = operators;
1444  foreach (QString dependeeName, dependees)
1445  {
1446  bool reverse = false;
1447  if (dependeeName.startsWith('!'))
1448  {
1449  reverse = true;
1450  dependeeName.remove(0,1);
1451  }
1452  MythUIType *dependee = GetChild(dependeeName);
1453 
1454  if (dependee)
1455  {
1456  QObject::connect(dependee, SIGNAL(DependChanged(bool)),
1457  dependant, SLOT(UpdateDependState(bool)));
1458  dependant->SetReverseDependence(dependee, reverse);
1459  dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, false));
1460  dependant->UpdateDependState(dependee, true);
1461  }
1462  else
1463  {
1464  dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, !reverse));
1465  dependant->UpdateDependState(dependee, reverse);
1466  }
1467  }
1468  }
1469  }
1470 
1471  if (recurse)
1472  {
1473  QList<MythUIType *>::iterator child;
1474  for (child = m_ChildrenList.begin(); child != m_ChildrenList.end(); ++child)
1475  {
1476  if (*child)
1477  (*child)->ConnectDependants(recurse);
1478  }
1479  }
1480 }
~MythUIType() override
Definition: mythuitype.cpp:59
#define VERBOSE_XML(type, level, filename, element, msg)
Definition: xmlparsebase.h:14
QPoint toQPoint(void) const
Definition: mythrect.cpp:522
QList< MythUIType * > * GetAllChildren(void)
Return a list of all child widgets.
Definition: mythuitype.cpp:194
void FinishedMoving()
void CalculateArea(const MythRect &parentArea)
Definition: mythrect.cpp:32
QList< QPair< MythUIType *, bool > > m_dependsValue
Definition: mythuitype.h:233
QString m_helptext
Definition: mythuitype.h:274
void setHeight(const QString &sHeight)
Definition: mythrect.cpp:241
QMap< QString, QString > m_dependsMap
Definition: mythuitype.h:229
void Show(void)
void FinishedFading()
bool AddFont(const QString &text, MythFontProperties *fontProp)
virtual MythPainter * GetPainter(void)
void SetDependsMap(QMap< QString, QString > dependsMap)
virtual bool keyPressEvent(QKeyEvent *event)
Key event handler.
Definition: mythuitype.cpp:972
void SetVerticalZoom(float zoom)
Definition: mythuitype.cpp:956
void LosingFocus()
void SetEnabled(bool enable)
QPoint m_XYDestination
Definition: mythuitype.h:265
void SetFocusOrder(int order)
void customEvent(QEvent *event) override
Definition: mythuitype.cpp:978
void ResetNeedsRedraw(void)
Definition: mythuitype.cpp:283
virtual void SetMinAreaParent(MythRect actual_area, MythRect allowed_area, MythUIType *child)
Adjust the size of sibling objects within the button.
Definition: mythuitype.cpp:686
void SetAlpha(int newalpha)
Definition: mythuitype.cpp:925
void SetRedraw(void)
Definition: mythuitype.cpp:293
void DeleteChild(const QString &name)
Delete a named child of this UIType.
Definition: mythuitype.cpp:145
MythRect m_MinArea
Definition: mythuitype.h:250
virtual bool gestureEvent(MythGestureEvent *event)
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop.
Definition: mythuitype.cpp:988
bool IsVisible(bool recurse=false) const
Definition: mythuitype.cpp:882
void LoseFocus()
void Enabling()
bool m_IsDependDefault
Definition: mythuitype.h:244
void HandleAlphaPulse()
Handle one frame of an alpha (transparency) change animation.
Definition: mythuitype.cpp:399
void SetHorizontalZoom(float zoom)
Definition: mythuitype.cpp:950
MythPainter * GetMythPainter(void)
FontMap * m_Fonts
Definition: mythuitype.h:268
void SetReverseDependence(MythUIType *dependee, bool reverse)
int CalcAlpha(int alphamod)
Definition: mythuitype.cpp:458
bool AddFont(const QString &text, MythFontProperties *fontProp)
QPointF GetCentre(const QRect &rect, int xoff, int yoff)
void SetColor(const QColor &color)
void DeleteAllChildren(void)
Delete all child widgets.
Definition: mythuitype.cpp:202
UIEffects m_Effects
Definition: mythuitype.h:257
void UpdateDependState(bool isDefault)
void ConnectDependants(bool recurse=false)
int m_focusOrder
Definition: mythuitype.h:247
QColor m_BorderColor
Definition: mythuitype.h:281
static int NormY(int height)
int m_AlphaMax
Definition: mythuitype.h:262
The base class on which all widgets and screens are based.
Definition: mythuitype.h:63
MythUIType(QObject *parent, const QString &name)
Definition: mythuitype.cpp:41
void CalculatePoint(const MythRect &parentArea)
Definition: mythrect.cpp:376
void SetPosition(int x, int y)
Convenience method, calls SetPosition(const MythPoint&) Override that instead to change functionality...
Definition: mythuitype.cpp:517
QList< MythUIAnimation * > m_animations
Definition: mythuitype.h:273
static MythPoint parsePoint(const QString &text, bool normalize=true)
void AddFocusableChildrenToList(QMap< int, MythUIType * > &focusList)
virtual void CreateCopy(MythUIType *parent)
Copy the state of this widget to the one given, it must be of the same type.
bool m_NeedsRedraw
Definition: mythuitype.h:255
virtual QRegion GetDirtyArea(void) const
Definition: mythuitype.cpp:877
Centre m_centre
void Hide(void)
virtual void SetVisible(bool visible)
void TakingFocus()
QRect toQRect(void) const
Definition: mythrect.cpp:362
int m_AlphaChange
Definition: mythuitype.h:260
void setRect(const QString &sX, const QString &sY, const QString &sWidth, const QString &sHeight, const QString &baseRes=QString())
Definition: mythrect.cpp:103
virtual void mediaEvent(MythMediaEvent *event)
Media/Device status event handler, received from MythMediaMonitor.
Definition: mythuitype.cpp:997
static void ParseElement(const QDomElement &element, MythUIType *parent)
bool MoveToTop(void)
A C++ ripoff of the stroke library for MythTV.
void Refresh(void)
virtual void VanishSibling(void)
Definition: mythuitype.cpp:663
void Activate()
virtual void SetMinArea(const MythRect &rect)
Set the minimum area based on the given size.
Definition: mythuitype.cpp:799
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 DependChanged(bool isDefault)
static QString getFirstText(QDomElement &element)
int m_AlphaMin
Definition: mythuitype.h:261
virtual void SetSize(const QSize &size)
Definition: mythuitype.cpp:548
static QObject * qChildHelper(const char *objName, const char *inheritsClass, bool recursiveSearch, const QObjectList &children)
Definition: mythuitype.cpp:93
bool m_CanHaveFocus
Definition: mythuitype.h:238
virtual void Pulse(void)
Pulse is called 70 times a second to trigger a single frame of an animation.
Definition: mythuitype.cpp:440
bool m_Initiator
Definition: mythuitype.h:241
Wrapper around QRect allowing us to handle percentage and other relative values for areas in mythui.
Definition: mythrect.h:17
void MoveTo(QPoint destXY, QPoint speedXY)
Definition: mythuitype.cpp:893
bool MoveChildToTop(MythUIType *child)
virtual void SetMinSize(const MythPoint &size)
Set the minimum size of this widget, for widgets which can be rescaled.
Definition: mythuitype.cpp:569
void moveLeft(const QString &sX)
Definition: mythrect.cpp:266
MythRect m_Area
Definition: mythuitype.h:249
MythUIType * GetChildAt(const QPoint &p, bool recursive=true, bool focusable=true) const
Return the first MythUIType at the given coordinates.
Definition: mythuitype.cpp:221
virtual void RecalculateArea(bool recurse=true)
void ExpandArea(const MythRect &rect)
Definition: mythuitype.cpp:848
virtual void AdjustMinArea(int delta_x, int delta_y, int delta_w, int delta_h)
Adjust the size of a sibling.
Definition: mythuitype.cpp:608
void setWidth(const QString &sWidth)
Definition: mythrect.cpp:230
virtual void DrawSelf(MythPainter *p, int xoffset, int yoffset, int alphaMod, QRect clipRect)
Definition: mythuitype.cpp:463
A custom event that represents a mouse gesture.
Definition: mythgesture.h:39
QRegion m_DirtyRegion
Definition: mythuitype.h:254
MythPainter * m_Painter
Definition: mythuitype.h:271
bool m_Visible
Definition: mythuitype.h:236
bool m_Vanish
Definition: mythuitype.h:242
QPoint m_XYSpeed
Definition: mythuitype.h:266
virtual QSize GetMinSize(void) const
Definition: mythuitype.cpp:581
int m_AlphaChangeMode
Definition: mythuitype.h:259
void AdjustAlpha(int mode, int alphachange, int minalpha=0, int maxalpha=255)
Definition: mythuitype.cpp:907
void HandleMovementPulse()
Handle one frame of a movement animation.
Definition: mythuitype.cpp:352
virtual void LoadNow(void)
Cause images in this and child widgets to be loaded.
MythMainWindow * GetMythMainWindow(void)
void Showing()
static int NormX(int width)
MythFontProperties * GetFont(const QString &text) const
virtual void SetArea(const MythRect &rect)
Definition: mythuitype.cpp:589
bool CanTakeFocus(void) const
Return if this widget can accept input focus.
Definition: mythuitype.cpp:334
virtual void Reset(void)
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitype.cpp:69
void SetDeferLoad(bool defer)
Definition: mythuitype.h:161
bool isValid(void) const
Definition: mythrect.h:97
bool IsDeferredLoading(bool recurse=false) const
void SetFace(const QFont &face)
virtual MythPoint GetPosition(void) const
Definition: mythuitype.cpp:543
MythFontProperties * GetFont(const QString &text)
virtual MythRect GetFullArea(void) const
Definition: mythuitype.cpp:872
MythPoint m_MinSize
Definition: mythuitype.h:251
QMap< MythUIType *, bool > m_ReverseDepend
Definition: mythuitype.h:245
bool m_Enabled
Definition: mythuitype.h:239
MythPoint topLeft(void) const
Definition: mythrect.cpp:252
bool m_Vanished
Definition: mythuitype.h:243
void moveTopLeft(const MythPoint &point)
Definition: mythrect.cpp:260
Trigger GetTrigger(void) const
virtual void CopyFrom(MythUIType *base)
Copy this widgets state from another.
bool NeedsRedraw(void) const
Definition: mythuitype.cpp:278
bool IsEnabled(void) const
Definition: mythuitype.h:94
MythUIType * m_Parent
Definition: mythuitype.h:270
static MythRect parseRect(const QString &text, bool normalize=true)
Wrapper around QPoint allowing us to handle percentage and other relative values for positioning in m...
Definition: mythrect.h:85
void SetChildNeedsRedraw(MythUIType *child)
Definition: mythuitype.cpp:309
static long int random(void)
Definition: compat.h:149
bool TakeFocus()
bool m_EnableInitiator
Definition: mythuitype.h:240
void SetDependIsDefault(bool isDefault)
void Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod=255, QRect clipRect=QRect())
Definition: mythuitype.cpp:468
bool ContainsPoint(const QPoint &point) const
Check if the given point falls within this widgets area.
void ActivateAnimations(MythUIAnimation::Trigger trigger)
Definition: mythuitype.cpp:268
void Disabling()
bool m_deferload
Definition: mythuitype.h:279
void moveTop(const QString &sY)
Definition: mythrect.cpp:276
void SetAngle(float angle)
Definition: mythuitype.cpp:962
void Hiding()
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:130
QList< int > m_dependOperator
Definition: mythuitype.h:234
bool m_Moving
Definition: mythuitype.h:264
static bool parseBool(const QString &text)
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:342
QList< MythUIType * > m_ChildrenList
Definition: mythuitype.h:228
virtual bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings)
Parse the xml definition of this widget setting the state of the object accordingly.
QString m_xmlLocation
Definition: mythuitype.h:277
void SetCentre(UIEffects::Centre centre)
Definition: mythuitype.cpp:939
void SetPointSize(uint points)
QString m_xmlName
Definition: mythuitype.h:276
void AddChild(MythUIType *child)
Add a child UIType.
Definition: mythuitype.cpp:85
void SetZoom(float zoom)
Definition: mythuitype.cpp:944
virtual void Finalize(void)
Perform any post-xml parsing initialisation tasks.
bool m_HasFocus
Definition: mythuitype.h:237
int GetAlpha(void) const
Definition: mythuitype.cpp:934