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 nullbrush(Qt::NoBrush);
502  QPen pen(m_BorderColor);
503  pen.setWidth(1);
504  p->DrawRect(realArea, nullbrush, 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, delta_y = 0, delta_w = 0, delta_h = 0;
692  MythRect area;
693 
694  // If a minsize is not set, don't use MinArea
695  if (!m_MinSize.isValid())
696  return;
697 
698  if (calling_child->m_Vanished)
699  {
700  actual_area.moveLeft(0);
701  actual_area.moveTop(0);
702  allowed_area.moveLeft(0);
703  allowed_area.moveTop(0);
704  }
705 
706  actual_area.translate(m_Area.x(), m_Area.y());
707  allowed_area.translate(m_Area.x(), m_Area.y());
708 
709  QList<MythUIType *>::iterator it;
710 
711  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
712  {
713  if (*it == calling_child || !(*it)->m_Initiator)
714  continue;
715 
716  if (!(*it)->m_Vanished)
717  {
718  // Find union of area(s)
719  area = (*it)->GetArea();
720  area.translate(m_Area.x(), m_Area.y());
721  actual_area = actual_area.united(area);
722 
723  area = (*it)->m_Area;
724  area.translate(m_Area.x(), m_Area.y());
725  allowed_area = allowed_area.united(area);
726  }
727  }
728 
729  // Make sure it is not larger than the area allowed
730  actual_area = actual_area.intersected(m_Area);
731  allowed_area = allowed_area.intersected(m_Area);
732 
733  if (m_Vanish && actual_area.size().isNull())
734  {
735  m_Vanished = true;
736  }
737  else
738  {
739  if (calling_child->m_Vanished)
740  {
741  delta_x = m_Area.x() - actual_area.x();
742  delta_y = m_Area.y() - actual_area.y();
743  delta_w = actual_area.width() - m_Area.width();
744  delta_h = actual_area.height() - m_Area.height();
745  }
746  else
747  {
748  delta_x = allowed_area.x() - actual_area.x();
749  delta_y = allowed_area.y() - actual_area.y();
750  delta_w = actual_area.width() - allowed_area.width();
751  delta_h = actual_area.height() - allowed_area.height();
752  }
753 
754  m_Vanished = false;
755  }
756 
757  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
758  {
759  if (*it == calling_child)
760  continue;
761 
762  if (!(*it)->m_Initiator)
763  {
764  if (m_Vanished)
765  (*it)->VanishSibling();
766  else
767  (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h);
768  }
769 
770  area = (*it)->GetArea();
771  area.translate(m_Area.topLeft());
772  actual_area = actual_area.united(area);
773  }
774 
775  if (m_Vanished)
776  {
777  m_MinArea.setRect(0, 0, 0, 0);
778  actual_area.setRect(0, 0, 0, 0);
779  }
780  else
781  {
782  QSize bound(actual_area.width(), actual_area.height());
783 
784  bound = bound.expandedTo(GetMinSize());
785  m_MinArea.setRect(actual_area.x(),
786  actual_area.y(),
787  actual_area.x() + bound.width(),
788  actual_area.y() + bound.height());
789  }
790 
791  if (m_Parent)
792  m_Parent->SetMinAreaParent(actual_area, m_Area, this);
793 }
794 
799 {
800  // If a minsize is not set, don't use MinArea
801  if (!m_Initiator || !m_MinSize.isValid())
802  return;
803 
804  QRect bounded(rect);
805  bool vanish = (m_Vanish && rect.isNull());
806 
807  if (vanish)
808  {
809  bounded.moveLeft(0);
810  bounded.moveTop(0);
811  }
812  else
813  {
814  QPoint center = bounded.center();
815 
816  if (bounded.isNull())
817  bounded.setSize(GetMinSize());
818  else
819  bounded.setSize(bounded.size().expandedTo(GetMinSize()));
820 
821  bounded.moveCenter(center);
822  if (bounded.x() + bounded.width() > m_Area.x() + m_Area.width())
823  bounded.moveRight(m_Area.x() + m_Area.width());
824  if (bounded.y() + bounded.height() > m_Area.y() + m_Area.height())
825  bounded.moveBottom(m_Area.y() + m_Area.height());
826  if (bounded.x() < m_Area.x())
827  {
828  bounded.moveLeft(m_Area.x());
829  if (bounded.width() > m_Area.width())
830  bounded.setWidth(m_Area.width());
831  }
832  if (bounded.y() < m_Area.y())
833  {
834  bounded.moveTop(m_Area.y());
835  if (bounded.height() > m_Area.height())
836  bounded.setHeight(m_Area.height());
837  }
838  }
839 
840  m_MinArea = bounded;
841  m_Vanished = vanish;
842 
843  if (m_Parent)
845 }
846 
848 {
849  QSize childSize = rect.size();
850  QSize size = m_Area.size();
851 
852  if (childSize == size)
853  return;
854 
855  SetSize(size.expandedTo(childSize));
856  SetRedraw();
857 }
858 
864 {
865  if (m_Vanished || m_MinArea.isValid())
866  return m_MinArea;
867 
868  return m_Area;
869 }
870 
872 {
873  return m_Area;
874 }
875 
876 QRegion MythUIType::GetDirtyArea(void) const
877 {
878  return m_DirtyRegion;
879 }
880 
881 bool MythUIType::IsVisible(bool recurse) const
882 {
883  if (recurse)
884  {
885  if (m_Parent && !m_Parent->IsVisible(recurse))
886  return false;
887  }
888 
889  return m_Visible;
890 }
891 
892 void MythUIType::MoveTo(QPoint destXY, QPoint speedXY)
893 {
894  if (!GetPainter()->SupportsAnimation())
895  return;
896 
897  if (destXY.x() == m_Area.x() && destXY.y() == m_Area.y())
898  return;
899 
900  m_Moving = true;
901 
902  m_XYDestination = destXY;
903  m_XYSpeed = speedXY;
904 }
905 
906 void MythUIType::AdjustAlpha(int mode, int alphachange, int minalpha,
907  int maxalpha)
908 {
909  if (!GetPainter()->SupportsAlpha())
910  return;
911 
912  m_AlphaChangeMode = mode;
913  m_AlphaChange = alphachange;
914  m_AlphaMin = minalpha;
915  m_AlphaMax = maxalpha;
916 
919 
922 }
923 
924 void MythUIType::SetAlpha(int newalpha)
925 {
926  if (m_Effects.m_alpha == newalpha)
927  return;
928 
929  m_Effects.m_alpha = newalpha;
930  SetRedraw();
931 }
932 
933 int MythUIType::GetAlpha(void) const
934 {
935  return m_Effects.m_alpha;
936 }
937 
939 {
940  m_Effects.m_centre = centre;
941 }
942 
943 void MythUIType::SetZoom(float zoom)
944 {
945  SetHorizontalZoom(zoom);
946  SetVerticalZoom(zoom);
947 }
948 
950 {
951  m_Effects.m_hzoom = zoom;
952  SetRedraw();
953 }
954 
956 {
957  m_Effects.m_vzoom = zoom;
958  SetRedraw();
959 }
960 
961 void MythUIType::SetAngle(float angle)
962 {
963  m_Effects.m_angle = angle;
964  SetRedraw();
965 }
966 
971 bool MythUIType::keyPressEvent(QKeyEvent * /*event*/)
972 {
973  return false;
974 }
975 
976 
977 void MythUIType::customEvent(QEvent * /*event*/)
978 {
979 }
980 
987 {
988  return false;
989 }
990 
996 {
997 }
998 
1000 {
1001  if (!m_CanHaveFocus || !m_HasFocus)
1002  return;
1003 
1004  emit LosingFocus();
1005  m_HasFocus = false;
1006  Refresh();
1007 }
1008 
1010 {
1011  if (!m_CanHaveFocus || m_HasFocus)
1012  return false;
1013 
1014  m_HasFocus = true;
1015  Refresh();
1016  emit TakingFocus();
1017  return true;
1018 }
1019 
1021 {
1022 }
1023 
1025 {
1026  SetRedraw();
1027 }
1028 
1029 void MythUIType::UpdateDependState(MythUIType *dependee, bool isDefault)
1030 {
1031  bool visible = false;
1032 
1033  if (dependee)
1034  {
1035  bool reverse = m_ReverseDepend[dependee];
1036  visible = reverse ? !isDefault : isDefault;
1037  for (int i = 0; i < m_dependsValue.size(); i++)
1038  {
1039  if (m_dependsValue[i].first != dependee)
1040  continue;
1041  m_dependsValue[i].second = visible;
1042  break;
1043  }
1044  }
1045 
1046  if (!m_dependsValue.empty())
1047  visible = m_dependsValue[0].second;
1048  for (int i = 1; i < m_dependsValue.size(); i++)
1049  {
1050  bool v = m_dependsValue[i].second;
1051 
1052  if (((i-1) < m_dependOperator.size()) &&
1053  m_dependOperator[i-1] == 1)
1054  {
1055  // OR operator
1056  visible = visible && v;
1057  }
1058  else
1059  {
1060  // AND operator
1061  visible = visible || v;
1062  }
1063  }
1064 
1065  m_IsDependDefault = visible;
1066 
1068 }
1069 
1070 void MythUIType::UpdateDependState(bool isDefault)
1071 {
1072  MythUIType *dependee = static_cast<MythUIType*>(sender());
1073 
1074  UpdateDependState(dependee, isDefault);
1075 }
1076 
1077 void MythUIType::SetVisible(bool visible)
1078 {
1079  if (visible == m_Visible)
1080  return;
1081 
1082  if (visible && m_IsDependDefault)
1083  return;
1084 
1085  m_Visible = visible;
1086  SetRedraw();
1087 
1088  if (m_Visible)
1089  emit Showing();
1090  else
1091  emit Hiding();
1092 }
1093 
1095 {
1096  m_IsDependDefault = isDefault;
1097 }
1098 
1099 void MythUIType::SetEnabled(bool enable)
1100 {
1101  if (m_Enabled != enable)
1102  m_Enabled = enable;
1103 
1104  if (enable)
1105  emit Enabling();
1106  else
1107  emit Disabling();
1108 }
1109 
1111 {
1112  SetVisible(false);
1113 }
1114 
1116 {
1117  SetVisible(true);
1118 }
1119 
1120 void MythUIType::AddFocusableChildrenToList(QMap<int, MythUIType *> &focusList)
1121 {
1122  if (m_CanHaveFocus)
1123  focusList.insertMulti(m_focusOrder, this);
1124 
1125  QList<MythUIType *>::Iterator it;
1126 
1127  for (it = m_ChildrenList.end() - 1; it != m_ChildrenList.begin() - 1; --it)
1128  (*it)->AddFocusableChildrenToList(focusList);
1129 }
1130 
1131 int MythUIType::NormX(const int width)
1132 {
1133  return GetMythMainWindow()->NormX(width);
1134 }
1135 
1136 int MythUIType::NormY(const int height)
1137 {
1138  return GetMythMainWindow()->NormY(height);
1139 }
1140 
1145 {
1146  m_xmlName = base->m_xmlName;
1147  m_xmlLocation = base->m_xmlLocation;
1148  m_Visible = base->m_Visible;
1149  m_Enabled = base->m_Enabled;
1151  m_focusOrder = base->m_focusOrder;
1152 
1153  m_Area = base->m_Area;
1154  RecalculateArea();
1155 
1157  m_MinSize = base->m_MinSize;
1158  m_Vanish = base->m_Vanish;
1159  m_Vanished = false;
1160  m_Effects = base->m_Effects;
1162  m_AlphaChange = base->m_AlphaChange;
1163  m_AlphaMin = base->m_AlphaMin;
1164  m_AlphaMax = base->m_AlphaMax;
1165 
1166  m_Moving = base->m_Moving;
1168  m_XYSpeed = base->m_XYSpeed;
1169  m_deferload = base->m_deferload;
1170 
1171  QList<MythUIAnimation*>::Iterator i;
1172  for (i = base->m_animations.begin(); i != base->m_animations.end(); ++i)
1173  {
1174  MythUIAnimation* animation = new MythUIAnimation(this);
1175  animation->CopyFrom(*i);
1176  m_animations.push_back(animation);
1177  }
1178 
1179  QList<MythUIType *>::Iterator it;
1180 
1181  for (it = base->m_ChildrenList.begin(); it != base->m_ChildrenList.end();
1182  ++it)
1183  {
1184  MythUIType *child = GetChild((*it)->objectName());
1185 
1186  if (child)
1187  child->CopyFrom(*it);
1188  else
1189  (*it)->CreateCopy(this);
1190  }
1191 
1192  m_dependsMap = base->m_dependsMap;
1193 
1194  SetMinArea(base->m_MinArea);
1195 }
1196 
1202 {
1203  // Calling CreateCopy on base type is not valid
1204 }
1205 
1211  const QString &filename, QDomElement &element, bool showWarnings)
1212 {
1213  //FIXME add movement etc.
1214 
1215  if (element.tagName() == "position")
1216  SetPosition(parsePoint(element));
1217  else if (element.tagName() == "area")
1218  {
1219  SetArea(parseRect(element));
1220  }
1221  else if (element.tagName() == "minsize")
1222  {
1223  // Use parsePoint so percentages can be used
1224  if (element.hasAttribute("initiator"))
1225  m_EnableInitiator = parseBool(element.attribute("initiator"));
1226 
1227  if (element.hasAttribute("vanish"))
1228  m_Vanish = parseBool(element.attribute("vanish"));
1229 
1230  SetMinSize(parsePoint(element));
1231  }
1232  else if (element.tagName() == "alpha")
1233  {
1234  m_Effects.m_alpha = getFirstText(element).toInt();
1235  m_AlphaChangeMode = 0;
1236  }
1237  else if (element.tagName() == "alphapulse")
1238  {
1239  m_AlphaChangeMode = 2;
1240  m_AlphaMin = element.attribute("min", "0").toInt();
1241  m_Effects.m_alpha = m_AlphaMax = element.attribute("max", "255").toInt();
1242 
1243  if (m_AlphaMax > 255)
1244  m_Effects.m_alpha = m_AlphaMax = 255;
1245 
1246  if (m_AlphaMin < 0)
1247  m_AlphaMin = 0;
1248 
1249  m_AlphaChange = element.attribute("change", "5").toInt();
1250  }
1251  else if (element.tagName() == "focusorder")
1252  {
1253  int order = getFirstText(element).toInt();
1254  SetFocusOrder(order);
1255  }
1256  else if (element.tagName() == "loadondemand")
1257  {
1258  SetDeferLoad(parseBool(element));
1259  }
1260  else if (element.tagName() == "helptext")
1261  {
1262  m_helptext = getFirstText(element);
1263  }
1264  else if (element.tagName() == "animation")
1265  {
1266  MythUIAnimation::ParseElement(element, this);
1267  }
1268  else {
1269  if (showWarnings) {
1270  VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
1271  QString("Unknown widget type '%1'").arg(element.tagName()));
1272  }
1273  return false;
1274  }
1275 
1276  return true;
1277 }
1278 
1287 {
1288 }
1289 
1290 MythFontProperties *MythUIType::GetFont(const QString &text) const
1291 {
1292  MythFontProperties *ret = m_Fonts->GetFont(text);
1293 
1294  if (!ret && m_Parent)
1295  return m_Parent->GetFont(text);
1296 
1297  return ret;
1298 }
1299 
1301 {
1302  return m_Fonts->AddFont(text, fontProp);
1303 }
1304 
1306 {
1307  if (m_Parent)
1309  else
1310  m_Area.CalculateArea(GetMythMainWindow()->GetUIScreenRect());
1311 
1312  if (recurse)
1313  {
1314  QList<MythUIType *>::iterator it;
1315 
1316  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
1317  {
1318  (*it)->RecalculateArea(recurse);
1319  }
1320  }
1321 }
1322 
1324 {
1325  m_focusOrder = order;
1326 }
1327 
1329 {
1330  if (!child)
1331  return false;
1332 
1333  int i = m_ChildrenList.indexOf(child);
1334 
1335  if (i != -1 || i != m_ChildrenList.size() - 1)
1336  {
1337  m_ChildrenList.removeAt(i);
1338  m_ChildrenList.append(child);
1339  child->SetRedraw();
1340  return true;
1341  }
1342 
1343  return false;
1344 }
1345 
1346 
1348 {
1349  if (m_Parent)
1350  {
1351  return m_Parent->MoveChildToTop(this);
1352  }
1353 
1354  return false;
1355 }
1356 
1357 bool MythUIType::IsDeferredLoading(bool recurse) const
1358 {
1359  if (m_deferload)
1360  return true;
1361 
1362  if (recurse && m_Parent)
1363  return m_Parent->IsDeferredLoading(recurse);
1364 
1365  return false;
1366 }
1367 
1374 {
1375  QList<MythUIType *>::Iterator it;
1376 
1377  for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
1378  (*it)->LoadNow();
1379 }
1380 
1386 bool MythUIType::ContainsPoint(const QPoint &point) const
1387 {
1388  return m_Area.contains(point);
1389 }
1390 
1392 {
1393  if (m_Painter)
1394  return m_Painter;
1395 
1396  if (m_Parent)
1397  return m_Parent->GetPainter();
1398 
1399  return GetMythPainter();
1400 }
1401 
1402 void MythUIType::SetDependsMap(QMap<QString, QString> dependsMap)
1403 {
1404  m_dependsMap = std::move(dependsMap);
1405 }
1406 
1407 void MythUIType::SetReverseDependence(MythUIType *dependee, bool reverse)
1408 {
1409  m_ReverseDepend.insert(dependee, reverse);
1410 }
1411 
1413 {
1414  QMapIterator<QString, QString> it(m_dependsMap);
1415  while(it.hasNext())
1416  {
1417  it.next();
1418 
1419  // build list of operators and dependeees.
1420  QStringList dependees;
1421  QList<int> operators;
1422  QString name = it.value();
1423  QStringList tmp1 = name.split("&");
1424  for (int i = 0; i < tmp1.size(); i++)
1425  {
1426  QStringList tmp2 = tmp1[i].split("|");
1427 
1428  dependees.append(tmp2[0]);
1429  for (int j = 1; j < tmp2.size(); j++)
1430  {
1431  dependees.append(tmp2[j]);
1432  operators.append(1); // 1 is OR
1433  }
1434  operators.append(2); // 2 is AND
1435  }
1436 
1437  MythUIType *dependant = GetChild(it.key());
1438  if (dependant)
1439  {
1440  dependant->m_dependOperator = operators;
1441  foreach (QString dependeeName, dependees)
1442  {
1443  bool reverse = false;
1444  if (dependeeName.startsWith('!'))
1445  {
1446  reverse = true;
1447  dependeeName.remove(0,1);
1448  }
1449  MythUIType *dependee = GetChild(dependeeName);
1450 
1451  if (dependee)
1452  {
1453  QObject::connect(dependee, SIGNAL(DependChanged(bool)),
1454  dependant, SLOT(UpdateDependState(bool)));
1455  dependant->SetReverseDependence(dependee, reverse);
1456  dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, false));
1457  dependant->UpdateDependState(dependee, true);
1458  }
1459  else
1460  {
1461  dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, !reverse));
1462  dependant->UpdateDependState(dependee, reverse);
1463  }
1464  }
1465  }
1466  }
1467 
1468  if (recurse)
1469  {
1470  QList<MythUIType *>::iterator child;
1471  for (child = m_ChildrenList.begin(); child != m_ChildrenList.end(); ++child)
1472  {
1473  if (*child)
1474  (*child)->ConnectDependants(recurse);
1475  }
1476  }
1477 }
#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
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:971
void SetVerticalZoom(float zoom)
Definition: mythuitype.cpp:955
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:977
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:924
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:986
bool IsVisible(bool recurse=false) const
Definition: mythuitype.cpp:881
void LoseFocus()
Definition: mythuitype.cpp:999
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:949
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)
bool ShowTypeNames(void)
Definition: mythpainter.h:97
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
void CopyFrom(const MythUIAnimation *animation)
virtual QRegion GetDirtyArea(void) const
Definition: mythuitype.cpp:876
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:995
static void ParseElement(const QDomElement &element, MythUIType *parent)
virtual void PushTransformation(const UIEffects &zoom, QPointF center=QPointF())
bool MoveToTop(void)
A C++ ripoff of the stroke library for MythTV.
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:798
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:863
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
virtual void DrawRect(const QRect &area, const QBrush &fillBrush, const QPen &linePen, int alpha)
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:892
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 DrawText(const QRect &r, const QString &msg, int flags, const MythFontProperties &font, int alpha, const QRect &boundRect)
Definition: mythpainter.cpp:78
virtual void RecalculateArea(bool recurse=true)
void ExpandArea(const MythRect &rect)
Definition: mythuitype.cpp:847
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
const char * name
Definition: ParseText.cpp:328
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:906
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 ShowBorders(void)
Definition: mythpainter.h:96
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:871
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:961
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:938
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:943
virtual void Finalize(void)
Perform any post-xml parsing initialisation tasks.
bool m_HasFocus
Definition: mythuitype.h:237
virtual void PopTransformation(void)
Definition: mythpainter.h:82
int GetAlpha(void) const
Definition: mythuitype.cpp:933