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