MythTV master
mythuitype.cpp
Go to the documentation of this file.
1
2// Own header
3#include "mythuitype.h"
4
5// C++ headers
6#include <algorithm>
7#include <utility>
8
9// QT headers
10#include <QDomDocument>
11#include <QEvent>
12#include <QKeyEvent>
13#include <QInputMethodEvent>
14
15// XML headers
16#include "xmlparsebase.h"
17
18// Mythbase headers
22#ifdef _MSC_VER
23# include "libmythbase/compat.h" // random
24#endif
25
26// MythUI headers
27#include "mythgesture.h"
28#include "mythimage.h"
29#include "mythpainter.h"
30#include "mythmainwindow.h"
31#include "mythfontproperties.h"
32#include "mythuitext.h"
33#include "mythuiimage.h"
34#include "mythuibutton.h"
35#include "mythuicheckbox.h"
36#include "mythuibuttonlist.h"
37#include "mythuitextedit.h"
38#include "mythuiprogressbar.h"
39#include "mythuispinbox.h"
40#include "mythuigroup.h"
41
42#define LOC QString("MythUIType: ")
43
44MythUIType::MythUIType(QObject *parent, const QString &name)
45 : QObject(parent)
46{
47 setObjectName(name);
48
49 if (parent)
50 {
51 m_parent = qobject_cast<MythUIType *>(parent);
52
53 if (m_parent)
54 m_parent->AddChild(this);
55 }
56
57 m_fonts = new FontMap();
58
59 // for debugging/theming
60 m_borderColor = QColor(MythRandom(0, 255), MythRandom(0, 255), MythRandom(0, 255));
61}
62
64{
65 delete m_fonts;
66 qDeleteAll(m_animations);
67}
68
74{
75 // Reset all children
76 QMutableListIterator<MythUIType *> it(m_childrenList);
77
78 while (it.hasNext())
79 {
80 it.next();
81 MythUIType *type = it.value();
82 type->Reset();
83 }
84}
85
90{
91 if (!child)
92 return;
93
94 m_childrenList.push_back(child);
95}
96
97static QObject *qChildHelper(const char *objName, const char *inheritsClass,
98 bool recursiveSearch, const QObjectList &children)
99{
100 if (children.isEmpty())
101 return nullptr;
102
103 bool onlyWidgets = (inheritsClass
104 && qstrcmp(inheritsClass, "QWidget") == 0);
105 const QLatin1String oName(objName);
106
107 for (auto *obj : std::as_const(children))
108 {
109 if (onlyWidgets)
110 {
111 if (obj->isWidgetType() && (!objName || obj->objectName() == oName))
112 return obj;
113 }
114 else if ((!inheritsClass || obj->inherits(inheritsClass))
115 && (!objName || obj->objectName() == oName))
116 {
117 return obj;
118 }
119
120 if (recursiveSearch && (qobject_cast<MythUIGroup *>(obj) != nullptr))
121 {
122 obj = qChildHelper(objName, inheritsClass, recursiveSearch,
123 obj->children());
124 if (obj != nullptr)
125 return obj;
126 }
127 }
128
129 return nullptr;
130}
131
138MythUIType *MythUIType::GetChild(const QString &name) const
139{
140 QObject *ret = qChildHelper(name.toLatin1().constData(), nullptr, true, children());
141
142 if (ret)
143 return qobject_cast<MythUIType *>(ret);
144
145 return nullptr;
146}
147
153void MythUIType::DeleteChild(const QString &name)
154{
155 QMutableListIterator<MythUIType *> it(m_childrenList);
156
157 while (it.hasNext())
158 {
159 it.next();
160 MythUIType *type = it.value();
161
162 if (type->objectName() == name)
163 {
164 delete type;
165 it.remove();
166 return;
167 }
168 }
169}
170
178{
179 if (!child)
180 return;
181
182 QMutableListIterator<MythUIType *> it(m_childrenList);
183
184 while (it.hasNext())
185 {
186 it.next();
187 MythUIType *type = it.value();
188
189 if (type == child)
190 {
191 delete type;
192 it.remove();
193 child = nullptr;
194 return;
195 }
196 }
197}
198
202QList<MythUIType *> *MythUIType::GetAllChildren(void)
203{
204 return &m_childrenList;
205}
206
207QList<MythUIType *> MythUIType::GetAllDescendants(void)
208{
209 QList<MythUIType *> descendants {};
210
211 for (const auto & item :std::as_const(m_childrenList))
212 {
213 descendants += item;
214 descendants += item->GetAllDescendants();
215 }
216 return descendants;
217}
218
223{
224 QList<MythUIType *>::iterator it;
225
226 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
227 if (*it)
228 delete *it;
229
230 m_childrenList.clear();
231}
232
241MythUIType *MythUIType::GetChildAt(const QPoint p, bool recursive,
242 bool focusable) const
243{
244 if (GetArea().contains(p))
245 {
246 if (!IsVisible() || !IsEnabled())
247 return nullptr;
248
249 if (m_childrenList.isEmpty())
250 return nullptr;
251
252 /* check all children */
253 QList<MythUIType *>::const_reverse_iterator it;
254
255 for (it = m_childrenList.rbegin(); it != m_childrenList.rend(); it++)
256 {
257 if (!(*it))
258 continue;
259
260 // If this point doesn't fall within the child's area then move on
261 // This requires that the area is actually accurate and in some
262 // cases this still isn't true
263 if (!(*it)->GetArea().contains(p - GetArea().topLeft()))
264 continue;
265
266
267 MythUIType *child = *it;
268
269 if (recursive && (focusable && !child->CanTakeFocus()))
270 child = child->GetChildAt(p - GetArea().topLeft(), recursive,
271 focusable);
272
273 if (child)
274 {
275 // NOTE: Assumes no selectible ui type will contain another
276 // selectible ui type.
277 if (focusable && !child->CanTakeFocus())
278 continue;
279
280 return child;
281 }
282 }
283 }
284
285 return nullptr;
286}
287
289{
290 for (MythUIAnimation* animation : std::as_const(m_animations))
291 if (animation->GetTrigger() == trigger)
292 animation->Activate();
293
294 for (MythUIType* uiType : std::as_const(m_childrenList))
295 uiType->ActivateAnimations(trigger);
296}
297
299{
300 return m_needsRedraw;
301}
302
304{
305 m_needsRedraw = false;
306
307 QList<MythUIType *>::Iterator it;
308
309 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
310 (*it)->ResetNeedsRedraw();
311}
312
314{
315 if (m_area.width() == 0 || m_area.height() == 0)
316 return;
317
318 m_needsRedraw = true;
319
320 if (m_dirtyRegion.isEmpty())
321 m_dirtyRegion = QRegion(m_area.toQRect());
322 else
323 m_dirtyRegion = m_dirtyRegion.united(QRegion(m_area.toQRect()));
324
325 if (m_parent)
327}
328
330{
331 QRegion childRegion = child->GetDirtyArea();
332
333 if (childRegion.isEmpty())
334 return;
335
336 childRegion.translate(m_area.x(), m_area.y());
337
338 childRegion = childRegion.intersected(m_area.toQRect());
339
340 m_needsRedraw = true;
341
342 if (m_dirtyRegion.isEmpty())
343 m_dirtyRegion = childRegion;
344 else
345 m_dirtyRegion = m_dirtyRegion.united(childRegion);
346
347 if (m_parent)
349}
350
355{
356 return m_canHaveFocus;
357}
358
363{
364 m_canHaveFocus = set;
365}
366
373{
374 if (!GetPainter()->SupportsAnimation())
375 return;
376
377 if (!m_moving)
378 return;
379
380 QPoint curXY = m_area.topLeft().toQPoint();
382
383 int xdir = m_xyDestination.x() - curXY.x();
384 int ydir = m_xyDestination.y() - curXY.y();
385
386 curXY.setX(curXY.x() + m_xySpeed.x());
387 curXY.setY(curXY.y() + m_xySpeed.y());
388
389 if ((xdir > 0 && curXY.x() >= m_xyDestination.x()) ||
390 (xdir < 0 && curXY.x() <= m_xyDestination.x()) ||
391 (xdir == 0))
392 {
393 m_xySpeed.setX(0);
394 }
395
396 if ((ydir > 0 && curXY.y() >= m_xyDestination.y()) ||
397 (ydir <= 0 && curXY.y() <= m_xyDestination.y()) ||
398 (ydir == 0))
399 {
400 m_xySpeed.setY(0);
401 }
402
403 SetRedraw();
404
405 if (m_xySpeed.x() == 0 && m_xySpeed.y() == 0)
406 {
407 m_moving = false;
408 emit FinishedMoving();
409 }
410
411 m_area.moveTopLeft(curXY);
412}
413
420{
421 if (!GetPainter()->SupportsAlpha() ||
422 !GetPainter()->SupportsAnimation())
423 return;
424
425 if (m_alphaChangeMode == 0)
426 return;
427
429
431
432 // Reached limits so change direction
434 {
435 if (m_alphaChangeMode == 2)
436 {
437 m_alphaChange *= -1;
438 }
439 else
440 {
442 m_alphaChange = 0;
443 emit FinishedFading();
444 }
445 }
446
447 SetRedraw();
448}
449
457{
458 if (!m_visible || m_vanished)
459 return;
460
463
464 QList<MythUIAnimation*>::Iterator i;
465 for (i = m_animations.begin(); i != m_animations.end(); ++i)
466 (*i)->IncrementCurrentTime();
467
468 QList<MythUIType *>::Iterator it;
469
470 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
471 (*it)->Pulse();
472}
473
474int MythUIType::CalcAlpha(int alphamod) const
475{
476 return (int)(m_effects.m_alpha * (alphamod / 255.0));
477}
478
479void MythUIType::DrawSelf(MythPainter * /*p*/, int /*xoffset*/, int /*yoffset*/,
480 int /*alphaMod*/, QRect /*clipRect*/)
481{
482}
483
484void MythUIType::Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod,
485 QRect clipRect)
486{
487 // NB m_dirtyRegion may be extended by HandleMovementPulse, SetRedraw
488 // or SetChildNeedsRedraw etc _AFTER_ GetDirtyArea is called.
489 // So clipRect may not include the whole of m_dirtyRegion
490 m_dirtyRegion -= QRegion(clipRect); // NB Qt >= 4.2
491
492 if (!m_visible || m_vanished)
493 return;
494
495 QRect realArea = m_area.toQRect();
496 realArea.translate(xoffset, yoffset);
497
498 if (!realArea.intersects(clipRect))
499 return;
500
501 p->PushTransformation(m_effects, m_effects.GetCentre(m_area, xoffset, yoffset));
502
503 DrawSelf(p, xoffset, yoffset, alphaMod, clipRect);
504
505 QList<MythUIType *>::Iterator it;
506
507 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
508 {
509 (*it)->Draw(p, xoffset + m_area.x(), yoffset + m_area.y(),
510 CalcAlpha(alphaMod), clipRect);
511 }
512
513 if (p->ShowBorders())
514 {
515 static const QBrush kNullBrush(Qt::NoBrush);
516 QPen pen(m_borderColor);
517 pen.setWidth(1);
518 p->DrawRect(realArea, kNullBrush, pen, 255);
519
520 if (p->ShowTypeNames())
521 {
523 font.SetFace(QFont("Droid Sans"));
525 font.SetPointSize(8);
526 p->DrawText(realArea, objectName(), 0, font, 255, realArea);
527 }
528 }
529
530 p->PopTransformation();
531}
532
533void MythUIType::SetPosition(int x, int y)
534{
535 SetPosition(MythPoint(x, y));
536}
537
538void MythUIType::SetPosition(QPoint point)
539{
540 SetPosition(MythPoint(point));
541}
542
544{
545 MythPoint pos(point);
546
547 if (m_parent)
549 else
550 pos.CalculatePoint(GetMythMainWindow()->GetUIScreenRect());
551
552 if (m_area.topLeft() == pos)
553 return;
554
555 m_dirtyRegion = QRegion(m_area.toQRect());
556
557 m_area.moveTopLeft(pos);
558
559 RecalculateArea(false);
560
561 SetRedraw();
562}
563
565{
566 return m_area.topLeft();
567}
568
569void MythUIType::SetSize(const QSize size)
570{
571 if (size == m_area.size())
572 return;
573
574 m_dirtyRegion = QRegion(m_area.toQRect());
575
576 m_area.setSize(size);
578
579 if (m_parent)
581
582 SetRedraw();
583}
584
591{
592 MythPoint point(minsize);
593
594 if (m_parent)
596
597 m_minSize = point;
598
599 SetRedraw();
600}
601
602QSize MythUIType::GetMinSize(void) const
603{
604 if (!m_minSize.isValid())
605 return m_area.size();
606
607 return {m_minSize.x(), m_minSize.y()};
608}
609
611{
612 if (rect == m_area)
613 return;
614
615 m_dirtyRegion = QRegion(m_area.toQRect());
616
617 m_area = rect;
619
620 if (m_parent)
622
623 SetRedraw();
624}
625
629void MythUIType::AdjustMinArea(int delta_x, int delta_y,
630 int delta_w, int delta_h)
631{
632 // If a minsize is not set, don't use MinArea
633 if (!m_minSize.isValid())
634 return;
635
636 // Delta's are negative values; knock down the area
637 QRect bounded(m_area.x() - delta_x,
638 m_area.y() - delta_y,
639 m_area.width() + delta_w,
640 m_area.height() + delta_h);
641
642 // Make sure we have not violated the min size
643 if (!bounded.isNull() || !m_vanish)
644 {
645 QPoint center = bounded.center();
646
647 if (bounded.isNull())
648 bounded.setSize(GetMinSize());
649 else
650 bounded.setSize(bounded.size().expandedTo(GetMinSize()));
651
652 bounded.moveCenter(center);
653 }
654
655 if (bounded.x() + bounded.width() > m_area.x() + m_area.width())
656 bounded.moveRight(m_area.x() + m_area.width());
657 if (bounded.y() + bounded.height() > m_area.y() + m_area.height())
658 bounded.moveBottom(m_area.y() + m_area.height());
659 if (bounded.x() < m_area.x())
660 {
661 bounded.moveLeft(m_area.x());
662 if (bounded.width() > m_area.width())
663 bounded.setWidth(m_area.width());
664 }
665 if (bounded.y() < m_area.y())
666 {
667 bounded.moveTop(m_area.y());
668 if (bounded.height() > m_area.height())
669 bounded.setHeight(m_area.height());
670 }
671
672 m_minArea = bounded;
673 m_vanished = false;
674
675 QList<MythUIType *>::iterator it;
676
677 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
678 {
679 if (!(*it)->m_initiator)
680 (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h);
681 }
682}
683
685{
686 if (!m_minSize.isValid() || !m_vanish)
687 return;
688
693 m_vanished = true;
694
695 QList<MythUIType *>::iterator it;
696
697 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
698 {
699 if (!(*it)->m_initiator)
700 (*it)->VanishSibling();
701 }
702}
703
707void MythUIType::SetMinAreaParent(MythRect actual_area, MythRect allowed_area,
708 MythUIType *calling_child)
709{
710 int delta_x = 0;
711 int delta_y = 0;
712 int delta_w = 0;
713 int delta_h = 0;
714 MythRect area;
715
716 // If a minsize is not set, don't use MinArea
717 if (!m_minSize.isValid())
718 return;
719
720 if (calling_child->m_vanished)
721 {
722 actual_area.moveLeft(0);
723 actual_area.moveTop(0);
724 allowed_area.moveLeft(0);
725 allowed_area.moveTop(0);
726 }
727
728 actual_area.translate(m_area.x(), m_area.y());
729 allowed_area.translate(m_area.x(), m_area.y());
730
731 QList<MythUIType *>::iterator it;
732
733 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
734 {
735 if (*it == calling_child || !(*it)->m_initiator)
736 continue;
737
738 if (!(*it)->m_vanished)
739 {
740 // Find union of area(s)
741 area = (*it)->GetArea();
742 area.translate(m_area.x(), m_area.y());
743 actual_area = actual_area.united(area);
744
745 area = (*it)->m_area;
746 area.translate(m_area.x(), m_area.y());
747 allowed_area = allowed_area.united(area);
748 }
749 }
750
751 // Make sure it is not larger than the area allowed
752 actual_area = actual_area.intersected(m_area);
753 allowed_area = allowed_area.intersected(m_area);
754
755 if (m_vanish && actual_area.size().isNull())
756 {
757 m_vanished = true;
758 }
759 else
760 {
761 if (calling_child->m_vanished)
762 {
763 delta_x = m_area.x() - actual_area.x();
764 delta_y = m_area.y() - actual_area.y();
765 delta_w = actual_area.width() - m_area.width();
766 delta_h = actual_area.height() - m_area.height();
767 }
768 else
769 {
770 delta_x = allowed_area.x() - actual_area.x();
771 delta_y = allowed_area.y() - actual_area.y();
772 delta_w = actual_area.width() - allowed_area.width();
773 delta_h = actual_area.height() - allowed_area.height();
774 }
775
776 m_vanished = false;
777 }
778
779 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
780 {
781 if (*it == calling_child)
782 continue;
783
784 if (!(*it)->m_initiator)
785 {
786 if (m_vanished)
787 (*it)->VanishSibling();
788 else
789 (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h);
790 }
791
792 area = (*it)->GetArea();
793 area.translate(m_area.topLeft());
794 actual_area = actual_area.united(area);
795 }
796
797 if (m_vanished)
798 {
799 m_minArea.setRect(0, 0, 0, 0);
800 actual_area.setRect(0, 0, 0, 0);
801 }
802 else
803 {
804 QSize bound(actual_area.width(), actual_area.height());
805
806 bound = bound.expandedTo(GetMinSize());
807 m_minArea.setRect(actual_area.x(),
808 actual_area.y(),
809 actual_area.x() + bound.width(),
810 actual_area.y() + bound.height());
811 }
812
813 if (m_parent)
814 m_parent->SetMinAreaParent(actual_area, m_area, this);
815}
816
821{
822 // If a minsize is not set, don't use MinArea
823 if (!m_initiator || !m_minSize.isValid())
824 return;
825
826 QRect bounded(rect);
827 bool vanish = (m_vanish && rect.isNull());
828
829 if (vanish)
830 {
831 bounded.moveLeft(0);
832 bounded.moveTop(0);
833 }
834 else
835 {
836 QPoint center = bounded.center();
837
838 if (bounded.isNull())
839 bounded.setSize(GetMinSize());
840 else
841 bounded.setSize(bounded.size().expandedTo(GetMinSize()));
842
843 bounded.moveCenter(center);
844 if (bounded.x() + bounded.width() > m_area.x() + m_area.width())
845 bounded.moveRight(m_area.x() + m_area.width());
846 if (bounded.y() + bounded.height() > m_area.y() + m_area.height())
847 bounded.moveBottom(m_area.y() + m_area.height());
848 if (bounded.x() < m_area.x())
849 {
850 bounded.moveLeft(m_area.x());
851 if (bounded.width() > m_area.width())
852 bounded.setWidth(m_area.width());
853 }
854 if (bounded.y() < m_area.y())
855 {
856 bounded.moveTop(m_area.y());
857 if (bounded.height() > m_area.height())
858 bounded.setHeight(m_area.height());
859 }
860 }
861
862 m_minArea = bounded;
863 m_vanished = vanish;
864
865 if (m_parent)
867}
868
869void MythUIType::ExpandArea(const QRect rect)
870{
871 QSize childSize = rect.size();
872 QSize size = m_area.size();
873
874 if (childSize == size)
875 return;
876
877 SetSize(size.expandedTo(childSize));
878 SetRedraw();
879}
880
886{
887 if (m_vanished || m_minArea.isValid())
888 return m_minArea;
889
890 return m_area;
891}
892
894{
895 return m_area;
896}
897
898QRegion MythUIType::GetDirtyArea(void) const
899{
900 return m_dirtyRegion;
901}
902
903bool MythUIType::IsVisible(bool recurse) const
904{
905 if (recurse)
906 {
907 if (m_parent && !m_parent->IsVisible(recurse))
908 return false;
909 }
910
911 return m_visible;
912}
913
914void MythUIType::MoveTo(QPoint destXY, QPoint speedXY)
915{
916 if (!GetPainter()->SupportsAnimation())
917 return;
918
919 if (destXY.x() == m_area.x() && destXY.y() == m_area.y())
920 return;
921
922 m_moving = true;
923
924 m_xyDestination = destXY;
925 m_xySpeed = speedXY;
926}
927
928void MythUIType::AdjustAlpha(int mode, int alphachange, int minalpha,
929 int maxalpha)
930{
931 if (!GetPainter()->SupportsAlpha())
932 return;
933
934 m_alphaChangeMode = mode;
935 m_alphaChange = alphachange;
936 m_alphaMin = minalpha;
937 m_alphaMax = maxalpha;
938
940}
941
942void MythUIType::SetAlpha(int newalpha)
943{
944 if (m_effects.m_alpha == newalpha)
945 return;
946
947 m_effects.m_alpha = newalpha;
948 SetRedraw();
949}
950
951int MythUIType::GetAlpha(void) const
952{
953 return m_effects.m_alpha;
954}
955
957{
958 m_effects.m_centre = centre;
959}
960
961void MythUIType::SetZoom(float zoom)
962{
963 SetHorizontalZoom(zoom);
964 SetVerticalZoom(zoom);
965}
966
968{
969 m_effects.m_hzoom = zoom;
970 SetRedraw();
971}
972
974{
975 m_effects.m_vzoom = zoom;
976 SetRedraw();
977}
978
979void MythUIType::SetAngle(float angle)
980{
981 m_effects.m_angle = angle;
982 SetRedraw();
983}
984
989bool MythUIType::keyPressEvent(QKeyEvent * /*event*/)
990{
991 return false;
992}
993
998bool MythUIType::inputMethodEvent(QInputMethodEvent * /*event*/)
999{
1000 return false;
1001}
1002
1003void MythUIType::customEvent(QEvent *event)
1004{
1005 QObject::customEvent(event);
1006}
1007
1014{
1015 return false;
1016}
1017
1023{
1024}
1025
1027{
1028 if (!m_canHaveFocus || !m_hasFocus)
1029 return;
1030
1031 emit LosingFocus();
1032 m_hasFocus = false;
1033 Refresh();
1034}
1035
1037{
1038 if (!m_canHaveFocus || m_hasFocus)
1039 return false;
1040
1041 m_hasFocus = true;
1042 Refresh();
1043 emit TakingFocus();
1044 return true;
1045}
1046
1047void MythUIType::SetFocusedName(const QString & widgetname)
1048{
1049 m_focusedName = widgetname;
1050 emit RequestUpdate();
1051}
1052
1054{
1055}
1056
1058{
1059 SetRedraw();
1060}
1061
1062void MythUIType::UpdateDependState(MythUIType *dependee, bool isDefault)
1063{
1064 bool visible = false;
1065
1066 if (dependee)
1067 {
1068 bool reverse = m_reverseDepend[dependee];
1069 visible = reverse ? !isDefault : isDefault;
1070 // NOLINTNEXTLINE(modernize-loop-convert)
1071 for (int i = 0; i < m_dependsValue.size(); i++)
1072 {
1073 if (m_dependsValue[i].first != dependee)
1074 continue;
1075 m_dependsValue[i].second = visible;
1076 break;
1077 }
1078 }
1079
1080 if (!m_dependsValue.empty())
1081 visible = m_dependsValue[0].second;
1082 for (int i = 1; i < m_dependsValue.size(); i++)
1083 {
1084 bool v = m_dependsValue[i].second;
1085
1086 if (((i-1) < m_dependOperator.size()) &&
1087 m_dependOperator[i-1] == 1)
1088 {
1089 // OR operator
1090 visible = visible && v;
1091 }
1092 else
1093 {
1094 // AND operator
1095 visible = visible || v;
1096 }
1097 }
1098
1099 m_isDependDefault = visible;
1100
1102}
1103
1105{
1106 auto *dependee = qobject_cast<MythUIType*>(sender());
1107
1108 UpdateDependState(dependee, isDefault);
1109}
1110
1111void MythUIType::SetVisible(bool visible)
1112{
1113 if (visible == m_visible)
1114 return;
1115
1116 if (visible && m_isDependDefault)
1117 return;
1118
1119 m_visible = visible;
1120 SetRedraw();
1121
1122 if (m_visible)
1123 emit Showing();
1124 else
1125 emit Hiding();
1127}
1128
1130{
1131 m_isDependDefault = isDefault;
1132}
1133
1134void MythUIType::SetEnabled(bool enable)
1135{
1136 if (m_enabled != enable)
1137 m_enabled = enable;
1138
1139 if (enable)
1140 emit Enabling();
1141 else
1142 emit Disabling();
1143}
1144
1146{
1147 SetVisible(false);
1148}
1149
1151{
1152 SetVisible(true);
1153}
1154
1156{
1157 if (m_canHaveFocus)
1158 focusList.insert(m_focusOrder, this);
1159
1160 for (auto it = m_childrenList.crbegin(); it != m_childrenList.crend(); ++it)
1161 (*it)->AddFocusableChildrenToList(focusList);
1162}
1163
1164int MythUIType::NormX(const int width)
1165{
1166 return GetMythMainWindow()->NormX(width);
1167}
1168
1169int MythUIType::NormY(const int height)
1170{
1171 return GetMythMainWindow()->NormY(height);
1172}
1173
1178{
1179 m_xmlName = base->m_xmlName;
1181 m_visible = base->m_visible;
1182 m_enabled = base->m_enabled;
1184 m_focusOrder = base->m_focusOrder;
1185
1186 m_area = base->m_area;
1188
1190 m_minSize = base->m_minSize;
1191 m_vanish = base->m_vanish;
1192 m_vanished = false;
1193 m_effects = base->m_effects;
1196 m_alphaMin = base->m_alphaMin;
1197 m_alphaMax = base->m_alphaMax;
1198
1199 m_moving = base->m_moving;
1201 m_xySpeed = base->m_xySpeed;
1202 m_deferload = base->m_deferload;
1203
1204 QList<MythUIAnimation*>::Iterator i;
1205 for (i = base->m_animations.begin(); i != base->m_animations.end(); ++i)
1206 {
1207 auto* animation = new MythUIAnimation(this);
1208 animation->CopyFrom(*i);
1209 m_animations.push_back(animation);
1210 }
1211
1212 QList<MythUIType *>::Iterator it;
1213
1214 for (it = base->m_childrenList.begin(); it != base->m_childrenList.end();
1215 ++it)
1216 {
1217 MythUIType *child = GetChild((*it)->objectName());
1218
1219 if (child)
1220 child->CopyFrom(*it);
1221 else
1222 (*it)->CreateCopy(this);
1223 }
1224
1225 m_dependsMap = base->m_dependsMap;
1226
1227 SetMinArea(base->m_minArea);
1228}
1229
1235{
1236 // Calling CreateCopy on base type is not valid
1237}
1238
1244 const QString &filename, QDomElement &element, bool showWarnings)
1245{
1246 //FIXME add movement etc.
1247
1248 if (element.tagName() == "position")
1249 SetPosition(parsePoint(element));
1250 else if (element.tagName() == "area")
1251 {
1252 SetArea(parseRect(element));
1253 }
1254 else if (element.tagName() == "minsize")
1255 {
1256 // Use parsePoint so percentages can be used
1257 if (element.hasAttribute("initiator"))
1258 m_enableInitiator = parseBool(element.attribute("initiator"));
1259
1260 if (element.hasAttribute("vanish"))
1261 m_vanish = parseBool(element.attribute("vanish"));
1262
1263 SetMinSize(parsePoint(element));
1264 }
1265 else if (element.tagName() == "alpha")
1266 {
1267 m_effects.m_alpha = getFirstText(element).toInt();
1269 }
1270 else if (element.tagName() == "alphapulse")
1271 {
1273 m_alphaMin = element.attribute("min", "0").toInt();
1274 m_effects.m_alpha = m_alphaMax = element.attribute("max", "255").toInt();
1275
1276 if (m_alphaMax > 255)
1278
1279 m_alphaMin = std::max(m_alphaMin, 0);
1280
1281 m_alphaChange = element.attribute("change", "5").toInt();
1282 }
1283 else if (element.tagName() == "focusorder")
1284 {
1285 int order = getFirstText(element).toInt();
1286 SetFocusOrder(order);
1287 }
1288 else if (element.tagName() == "loadondemand")
1289 {
1290 SetDeferLoad(parseBool(element));
1291 }
1292 else if (element.tagName() == "helptext")
1293 {
1294 m_helptext = getFirstText(element);
1295 }
1296 else if (element.tagName() == "animation")
1297 {
1298 MythUIAnimation::ParseElement(element, this);
1299 }
1300 else {
1301 if (showWarnings) {
1302 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
1303 QString("Unknown widget type '%1'").arg(element.tagName()));
1304 }
1305 return false;
1306 }
1307
1308 return true;
1309}
1310
1319{
1320}
1321
1322MythFontProperties *MythUIType::GetFont(const QString &text) const
1323{
1324 MythFontProperties *ret = m_fonts->GetFont(text);
1325
1326 if (!ret && m_parent)
1327 return m_parent->GetFont(text);
1328
1329 return ret;
1330}
1331
1333{
1334 return m_fonts->AddFont(text, fontProp);
1335}
1336
1338{
1339 if (m_parent)
1341 else
1342 m_area.CalculateArea(GetMythMainWindow()->GetUIScreenRect());
1343
1344 if (recurse)
1345 {
1346 QList<MythUIType *>::iterator it;
1347
1348 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
1349 {
1350 (*it)->RecalculateArea(recurse);
1351 }
1352 }
1353}
1354
1356{
1357 m_focusOrder = order;
1358}
1359
1361{
1362 if (!child)
1363 return false;
1364
1365 int i = m_childrenList.indexOf(child);
1366
1367 if (i != -1 || i != m_childrenList.size() - 1)
1368 {
1369 m_childrenList.removeAt(i);
1370 m_childrenList.append(child);
1371 child->SetRedraw();
1372 return true;
1373 }
1374
1375 return false;
1376}
1377
1378
1380{
1381 if (m_parent)
1382 {
1383 return m_parent->MoveChildToTop(this);
1384 }
1385
1386 return false;
1387}
1388
1389bool MythUIType::IsDeferredLoading(bool recurse) const
1390{
1391 if (m_deferload)
1392 return true;
1393
1394 if (recurse && m_parent)
1395 return m_parent->IsDeferredLoading(recurse);
1396
1397 return false;
1398}
1399
1406{
1407 QList<MythUIType *>::Iterator it;
1408
1409 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
1410 (*it)->LoadNow();
1411}
1412
1418bool MythUIType::ContainsPoint(const QPoint point) const
1419{
1420 return m_area.contains(point);
1421}
1422
1424{
1425 if (m_painter)
1426 return m_painter;
1427
1428 if (m_parent)
1429 return m_parent->GetPainter();
1430
1431 return GetMythPainter();
1432}
1433
1434void MythUIType::SetDependsMap(QMap<QString, QString> dependsMap)
1435{
1436 m_dependsMap = std::move(dependsMap);
1437}
1438
1440{
1441 m_reverseDepend.insert(dependee, reverse);
1442}
1443
1445{
1446 QMapIterator<QString, QString> it(m_dependsMap);
1447 QStringList dependees;
1448 QList<int> operators;
1449 while(it.hasNext())
1450 {
1451 it.next();
1452
1453 // build list of operators and dependeees.
1454 dependees.clear();
1455 operators.clear();
1456 QString name = it.value();
1457 QStringList tmp1 = name.split("&");
1458 for (const QString& t1 : std::as_const(tmp1))
1459 {
1460 QStringList tmp2 = t1.split("|");
1461
1462 dependees.append(tmp2[0]);
1463 for (int j = 1; j < tmp2.size(); j++)
1464 {
1465 dependees.append(tmp2[j]);
1466 operators.append(1); // 1 is OR
1467 }
1468 operators.append(2); // 2 is AND
1469 }
1470
1471 MythUIType *dependant = GetChild(it.key());
1472 if (dependant)
1473 {
1474 dependant->m_dependOperator = operators;
1475 for (QString dependeeName : std::as_const(dependees))
1476 {
1477 bool reverse = false;
1478 if (dependeeName.startsWith('!'))
1479 {
1480 reverse = true;
1481 dependeeName.remove(0,1);
1482 }
1483 MythUIType *dependee = GetChild(dependeeName);
1484
1485 if (dependee)
1486 {
1487 QObject::connect(dependee, &MythUIType::DependChanged,
1488 dependant, qOverload<bool>(&MythUIType::UpdateDependState));
1489 dependant->SetReverseDependence(dependee, reverse);
1490 dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, false));
1491 dependant->UpdateDependState(dependee, true);
1492 }
1493 else
1494 {
1495 dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, !reverse));
1496 dependant->UpdateDependState(dependee, reverse);
1497 }
1498 }
1499 }
1500 }
1501
1502 if (recurse)
1503 {
1504 QList<MythUIType *>::iterator child;
1505 for (child = m_childrenList.begin(); child != m_childrenList.end(); ++child)
1506 {
1507 if (*child)
1508 (*child)->ConnectDependants(recurse);
1509 }
1510 }
1511}
bool AddFont(const QString &text, MythFontProperties *fontProp)
MythFontProperties * GetFont(const QString &text)
void SetFace(const QFont &face)
void SetColor(const QColor &color)
void SetPointSize(uint points)
A custom event that represents a mouse gesture.
Definition: mythgesture.h:40
Wrapper around QPoint allowing us to handle percentage and other relative values for positioning in m...
Definition: mythrect.h:89
void CalculatePoint(QRect parentArea)
Definition: mythrect.cpp:444
bool isValid(void) const
Definition: mythrect.h:102
QPoint toQPoint(void) const
Definition: mythrect.cpp:594
Wrapper around QRect allowing us to handle percentage and other relative values for areas in mythui.
Definition: mythrect.h:18
void setRect(const QString &sX, const QString &sY, const QString &sWidth, const QString &sHeight, const QString &baseRes=QString())
Definition: mythrect.cpp:139
MythPoint topLeft(void) const
Definition: mythrect.cpp:288
void moveTop(const QString &sY)
Definition: mythrect.cpp:319
void moveLeft(const QString &sX)
Definition: mythrect.cpp:309
void setWidth(const QString &sWidth)
Definition: mythrect.cpp:266
void setHeight(const QString &sHeight)
Definition: mythrect.cpp:277
void CalculateArea(QRect parentArea)
Definition: mythrect.cpp:64
void moveTopLeft(QPoint point)
Definition: mythrect.cpp:296
QRect toQRect(void) const
Definition: mythrect.cpp:405
static void ParseElement(const QDomElement &element, MythUIType *parent)
int NormX(int X) const
int NormY(int Y) const
The base class on which all widgets and screens are based.
Definition: mythuitype.h:86
bool IsEnabled(void) const
Definition: mythuitype.h:119
bool m_enableInitiator
Definition: mythuitype.h:267
void SetZoom(float zoom)
Definition: mythuitype.cpp:961
void AddFocusableChildrenToList(FocusInfoType &focusList)
bool AddFont(const QString &text, MythFontProperties *fontProp)
QList< MythUIType * > * GetAllChildren(void)
Return a list of all child widgets.
Definition: mythuitype.cpp:202
int m_focusOrder
Definition: mythuitype.h:275
bool ContainsPoint(QPoint point) const
Check if the given point falls within this widgets area.
virtual void RecalculateArea(bool recurse=true)
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:362
void SetDependsMap(QMap< QString, QString > dependsMap)
virtual QRegion GetDirtyArea(void) const
Definition: mythuitype.cpp:898
bool IsVisible(bool recurse=false) const
Definition: mythuitype.cpp:903
virtual void SetSize(QSize size)
Definition: mythuitype.cpp:569
bool m_initiator
Definition: mythuitype.h:268
void VisibilityChanged(bool Visible)
void TakingFocus(void)
bool m_moving
Definition: mythuitype.h:291
void HandleMovementPulse()
Handle one frame of a movement animation.
Definition: mythuitype.cpp:372
void AddChild(MythUIType *child)
Add a child UIType.
Definition: mythuitype.cpp:89
void Hiding(void)
int m_alphaMax
Definition: mythuitype.h:289
MythRect m_minArea
Definition: mythuitype.h:278
void ActivateAnimations(MythUIAnimation::Trigger trigger)
Definition: mythuitype.cpp:288
bool m_vanished
Definition: mythuitype.h:270
void RequestUpdate(void)
void SetFocusOrder(int order)
UIEffects m_effects
Definition: mythuitype.h:284
virtual void mediaEvent(MythMediaEvent *event)
Media/Device status event handler, received from MythMediaMonitor.
void customEvent(QEvent *event) override
virtual void DrawSelf(MythPainter *p, int xoffset, int yoffset, int alphaMod, QRect clipRect)
Definition: mythuitype.cpp:479
virtual void VanishSibling(void)
Definition: mythuitype.cpp:684
void Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod=255, QRect clipRect=QRect())
Definition: mythuitype.cpp:484
bool CanTakeFocus(void) const
Return if this widget can accept input focus.
Definition: mythuitype.cpp:354
virtual void SetVisible(bool visible)
virtual MythPainter * GetPainter(void)
int m_alphaChangeMode
Definition: mythuitype.h:286
bool m_isDependDefault
Definition: mythuitype.h:271
QPoint m_xyDestination
Definition: mythuitype.h:292
QString m_xmlName
Definition: mythuitype.h:303
void AdjustAlpha(int mode, int alphachange, int minalpha=0, int maxalpha=255)
Definition: mythuitype.cpp:928
void Activate(void)
virtual void SetArea(const MythRect &rect)
Definition: mythuitype.cpp:610
void Disabling(void)
virtual void LoadNow(void)
Cause images in this and child widgets to be loaded.
bool m_vanish
Definition: mythuitype.h:269
virtual bool gestureEvent(MythGestureEvent *event)
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop.
void ExpandArea(QRect rect)
Definition: mythuitype.cpp:869
virtual QSize GetMinSize(void) const
Definition: mythuitype.cpp:602
MythUIType(QObject *parent, const QString &name)
Definition: mythuitype.cpp:44
void LoseFocus(void)
QPoint m_xySpeed
Definition: mythuitype.h:293
virtual void AdjustMinArea(int delta_x, int delta_y, int delta_w, int delta_h)
Adjust the size of a sibling.
Definition: mythuitype.cpp:629
bool m_needsRedraw
Definition: mythuitype.h:282
QList< int > m_dependOperator
Definition: mythuitype.h:261
MythPoint m_minSize
Definition: mythuitype.h:279
QMap< MythUIType *, bool > m_reverseDepend
Definition: mythuitype.h:272
void SetEnabled(bool enable)
void SetAngle(float angle)
Definition: mythuitype.cpp:979
virtual void CopyFrom(MythUIType *base)
Copy this widgets state from another.
virtual void Finalize(void)
Perform any post-xml parsing initialisation tasks.
bool NeedsRedraw(void) const
Definition: mythuitype.cpp:298
MythUIType * GetChildAt(QPoint p, bool recursive=true, bool focusable=true) const
Return the first MythUIType at the given coordinates.
Definition: mythuitype.cpp:241
void ResetNeedsRedraw(void)
Definition: mythuitype.cpp:303
void SetRedraw(void)
Definition: mythuitype.cpp:313
bool TakeFocus(void)
void Enabling(void)
void SetFocusedName(const QString &widgetname)
void ConnectDependants(bool recurse=false)
void SetVerticalZoom(float zoom)
Definition: mythuitype.cpp:973
virtual void SetMinArea(const MythRect &rect)
Set the minimum area based on the given size.
Definition: mythuitype.cpp:820
virtual void Pulse(void)
Pulse is called 70 times a second to trigger a single frame of an animation.
Definition: mythuitype.cpp:456
void Hide(void)
void SetChildNeedsRedraw(MythUIType *child)
Definition: mythuitype.cpp:329
FontMap * m_fonts
Definition: mythuitype.h:295
static int NormY(int height)
MythFontProperties * GetFont(const QString &text) const
void Refresh(void)
QString m_xmlLocation
Definition: mythuitype.h:304
void SetReverseDependence(MythUIType *dependee, bool reverse)
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:885
bool IsDeferredLoading(bool recurse=false) const
virtual void CreateCopy(MythUIType *parent)
Copy the state of this widget to the one given, it must be of the same type.
MythUIType * m_parent
Definition: mythuitype.h:297
bool m_canHaveFocus
Definition: mythuitype.h:265
void SetDependIsDefault(bool isDefault)
~MythUIType() override
Definition: mythuitype.cpp:63
QMap< QString, QString > m_dependsMap
Definition: mythuitype.h:256
bool m_enabled
Definition: mythuitype.h:266
virtual MythRect GetFullArea(void) const
Definition: mythuitype.cpp:893
int m_alphaMin
Definition: mythuitype.h:288
bool m_hasFocus
Definition: mythuitype.h:264
void DeleteAllChildren(void)
Delete all child widgets.
Definition: mythuitype.cpp:222
QString m_focusedName
Definition: mythuitype.h:274
int CalcAlpha(int alphamod) const
Definition: mythuitype.cpp:474
bool m_visible
Definition: mythuitype.h:263
virtual void SetMinAreaParent(MythRect actual_area, MythRect allowed_area, MythUIType *child)
Adjust the size of sibling objects within the button.
Definition: mythuitype.cpp:707
MythPainter * m_painter
Definition: mythuitype.h:298
void SetPosition(int x, int y)
Convenience method, calls SetPosition(const MythPoint&) Override that instead to change functionality...
Definition: mythuitype.cpp:533
QList< MythUIAnimation * > m_animations
Definition: mythuitype.h:300
void UpdateDependState(bool isDefault)
void HandleAlphaPulse()
Handle one frame of an alpha (transparency) change animation.
Definition: mythuitype.cpp:419
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:138
bool MoveToTop(void)
void SetAlpha(int newalpha)
Definition: mythuitype.cpp:942
void SetCentre(UIEffects::Centre centre)
Definition: mythuitype.cpp:956
void MoveTo(QPoint destXY, QPoint speedXY)
Definition: mythuitype.cpp:914
virtual bool inputMethodEvent(QInputMethodEvent *event)
Input Method event handler.
Definition: mythuitype.cpp:998
void DeleteChild(const QString &name)
Delete a named child of this UIType.
Definition: mythuitype.cpp:153
void SetHorizontalZoom(float zoom)
Definition: mythuitype.cpp:967
QColor m_borderColor
Definition: mythuitype.h:308
void DependChanged(bool isDefault)
virtual void Reset(void)
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitype.cpp:73
virtual bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings)
Parse the xml definition of this widget setting the state of the object accordingly.
void Show(void)
void FinishedMoving(void)
void Showing(void)
QList< MythUIType * > m_childrenList
Definition: mythuitype.h:255
void FinishedFading(void)
static int NormX(int width)
void SetDeferLoad(bool defer)
Definition: mythuitype.h:188
virtual void SetMinSize(const MythPoint &size)
Set the minimum size of this widget, for widgets which can be rescaled.
Definition: mythuitype.cpp:590
virtual bool keyPressEvent(QKeyEvent *event)
Key event handler.
Definition: mythuitype.cpp:989
MythRect m_area
Definition: mythuitype.h:277
QList< MythUIType * > GetAllDescendants(void)
Definition: mythuitype.cpp:207
int m_alphaChange
Definition: mythuitype.h:287
virtual MythPoint GetPosition(void) const
Definition: mythuitype.cpp:564
QRegion m_dirtyRegion
Definition: mythuitype.h:281
QList< QPair< MythUIType *, bool > > m_dependsValue
Definition: mythuitype.h:260
QString m_helptext
Definition: mythuitype.h:301
void LosingFocus(void)
bool m_deferload
Definition: mythuitype.h:306
int GetAlpha(void) const
Definition: mythuitype.cpp:951
bool MoveChildToTop(MythUIType *child)
Centre m_centre
QPointF GetCentre(const QRect rect, int xoff, int yoff) const
static MythRect parseRect(const QString &text, bool normalize=true)
static MythPoint parsePoint(const QString &text, bool normalize=true)
static QString getFirstText(QDomElement &element)
static bool parseBool(const QString &text)
A C++ ripoff of the stroke library for MythTV.
MythPainter * GetMythPainter(void)
MythMainWindow * GetMythMainWindow(void)
Convenience inline random number generator functions.
static QObject * qChildHelper(const char *objName, const char *inheritsClass, bool recursiveSearch, const QObjectList &children)
Definition: mythuitype.cpp:97
QMultiMap< int, MythUIType * > FocusInfoType
Definition: mythuitype.h:39
uint32_t MythRandom()
generate 32 random bits
Definition: mythrandom.h:20
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:206
#define VERBOSE_XML(type, level, filename, element, msg)
Definition: xmlparsebase.h:15