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 <ranges>
8#include <utility>
9
10// QT headers
11#include <QDomDocument>
12#include <QEvent>
13#include <QKeyEvent>
14#include <QInputMethodEvent>
15
16// XML headers
17#include "xmlparsebase.h"
18
19// Mythbase headers
23
24// MythUI headers
25#include "mythgesture.h"
26#include "mythimage.h"
27#include "mythpainter.h"
28#include "mythmainwindow.h"
29#include "mythfontproperties.h"
30#include "mythuitext.h"
31#include "mythuiimage.h"
32#include "mythuibutton.h"
33#include "mythuicheckbox.h"
34#include "mythuibuttonlist.h"
35#include "mythuitextedit.h"
36#include "mythuiprogressbar.h"
37#include "mythuispinbox.h"
38#include "mythuigroup.h"
39
40#define LOC QString("MythUIType: ")
41
42MythUIType::MythUIType(QObject *parent, const QString &name)
43 : QObject(parent)
44{
45 setObjectName(name);
46
47 if (parent)
48 {
49 m_parent = qobject_cast<MythUIType *>(parent);
50
51 if (m_parent)
52 m_parent->AddChild(this);
53 }
54
55 m_fonts = new FontMap();
56
57 // for debugging/theming
58 m_borderColor = QColor(MythRandom(0, 255), MythRandom(0, 255), MythRandom(0, 255));
59}
60
62{
63 delete m_fonts;
64 qDeleteAll(m_animations);
65}
66
72{
73 // Reset all children
74 for (auto *type : std::as_const(m_childrenList))
75 type->Reset();
76}
77
82{
83 if (!child)
84 return;
85
86 m_childrenList.push_back(child);
87}
88
89static QObject *qChildHelper(const char *objName, const char *inheritsClass,
90 bool recursiveSearch, const QObjectList &children)
91{
92 if (children.isEmpty())
93 return nullptr;
94
95 bool onlyWidgets = (inheritsClass
96 && qstrcmp(inheritsClass, "QWidget") == 0);
97 const QLatin1String oName(objName);
98
99 for (auto *obj : std::as_const(children))
100 {
101 if (onlyWidgets)
102 {
103 if (obj->isWidgetType() && (!objName || obj->objectName() == oName))
104 return obj;
105 }
106 else if ((!inheritsClass || obj->inherits(inheritsClass))
107 && (!objName || obj->objectName() == oName))
108 {
109 return obj;
110 }
111
112 if (recursiveSearch && (qobject_cast<MythUIGroup *>(obj) != nullptr))
113 {
114 obj = qChildHelper(objName, inheritsClass, recursiveSearch,
115 obj->children());
116 if (obj != nullptr)
117 return obj;
118 }
119 }
120
121 return nullptr;
122}
123
130MythUIType *MythUIType::GetChild(const QString &name) const
131{
132 QObject *ret = qChildHelper(name.toLatin1().constData(), nullptr, true, children());
133
134 if (ret)
135 return qobject_cast<MythUIType *>(ret);
136
137 return nullptr;
138}
139
145void MythUIType::DeleteChild(const QString &name)
146{
147 for (auto it = m_childrenList.begin(); it != m_childrenList.end(); /* no inc*/)
148 {
149 MythUIType *type = *it;
150 if (type->objectName() == name)
151 {
152 delete type;
153 it = m_childrenList.erase(it);
154 return;
155 }
156 ++it;
157 }
158}
159
167{
168 if (!child)
169 return;
170
171 for (auto it = m_childrenList.begin(); it != m_childrenList.end(); /* no inc */)
172 {
173 MythUIType *type = *it;
174 if (type == child)
175 {
176 delete type;
177 it = m_childrenList.erase(it);
178 child = nullptr;
179 return;
180 }
181 ++it;
182 }
183}
184
188QList<MythUIType *> *MythUIType::GetAllChildren(void)
189{
190 return &m_childrenList;
191}
192
193QList<MythUIType *> MythUIType::GetAllDescendants(void)
194{
195 QList<MythUIType *> descendants {};
196
197 for (const auto & item :std::as_const(m_childrenList))
198 {
199 descendants += item;
200 descendants += item->GetAllDescendants();
201 }
202 return descendants;
203}
204
209{
210 QList<MythUIType *>::iterator it;
211
212 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
213 if (*it)
214 delete *it;
215
216 m_childrenList.clear();
217}
218
227MythUIType *MythUIType::GetChildAt(const QPoint p, bool recursive,
228 bool focusable) const
229{
230 if (GetArea().contains(p))
231 {
232 if (!IsVisible() || !IsEnabled())
233 return nullptr;
234
235 if (m_childrenList.isEmpty())
236 return nullptr;
237
238 /* check all children */
239 QList<MythUIType *>::const_reverse_iterator it;
240
241 for (it = m_childrenList.rbegin(); it != m_childrenList.rend(); it++)
242 {
243 if (!(*it))
244 continue;
245
246 // If this point doesn't fall within the child's area then move on
247 // This requires that the area is actually accurate and in some
248 // cases this still isn't true
249 if (!(*it)->GetArea().contains(p - GetArea().topLeft()))
250 continue;
251
252
253 MythUIType *child = *it;
254
255 if (recursive && (focusable && !child->CanTakeFocus()))
256 child = child->GetChildAt(p - GetArea().topLeft(), recursive,
257 focusable);
258
259 if (child)
260 {
261 // NOTE: Assumes no selectible ui type will contain another
262 // selectible ui type.
263 if (focusable && !child->CanTakeFocus())
264 continue;
265
266 return child;
267 }
268 }
269 }
270
271 return nullptr;
272}
273
275{
276 for (MythUIAnimation* animation : std::as_const(m_animations))
277 if (animation->GetTrigger() == trigger)
278 animation->Activate();
279
280 for (MythUIType* uiType : std::as_const(m_childrenList))
281 uiType->ActivateAnimations(trigger);
282}
283
285{
286 return m_needsRedraw;
287}
288
290{
291 m_needsRedraw = false;
292
293 QList<MythUIType *>::Iterator it;
294
295 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
296 (*it)->ResetNeedsRedraw();
297}
298
300{
301 if (m_area.width() == 0 || m_area.height() == 0)
302 return;
303
304 m_needsRedraw = true;
305
306 if (m_dirtyRegion.isEmpty())
307 m_dirtyRegion = QRegion(m_area.toQRect());
308 else
309 m_dirtyRegion = m_dirtyRegion.united(QRegion(m_area.toQRect()));
310
311 if (m_parent)
313}
314
316{
317 QRegion childRegion = child->GetDirtyArea();
318
319 if (childRegion.isEmpty())
320 return;
321
322 childRegion.translate(m_area.x(), m_area.y());
323
324 childRegion = childRegion.intersected(m_area.toQRect());
325
326 m_needsRedraw = true;
327
328 if (m_dirtyRegion.isEmpty())
329 m_dirtyRegion = childRegion;
330 else
331 m_dirtyRegion = m_dirtyRegion.united(childRegion);
332
333 if (m_parent)
335}
336
341{
342 return m_canHaveFocus;
343}
344
349{
350 m_canHaveFocus = set;
351}
352
359{
360 if (!GetPainter()->SupportsAnimation())
361 return;
362
363 if (!m_moving)
364 return;
365
366 QPoint curXY = m_area.topLeft().toQPoint();
368
369 int xdir = m_xyDestination.x() - curXY.x();
370 int ydir = m_xyDestination.y() - curXY.y();
371
372 curXY.setX(curXY.x() + m_xySpeed.x());
373 curXY.setY(curXY.y() + m_xySpeed.y());
374
375 if ((xdir > 0 && curXY.x() >= m_xyDestination.x()) ||
376 (xdir < 0 && curXY.x() <= m_xyDestination.x()) ||
377 (xdir == 0))
378 {
379 m_xySpeed.setX(0);
380 }
381
382 if ((ydir > 0 && curXY.y() >= m_xyDestination.y()) ||
383 (ydir <= 0 && curXY.y() <= m_xyDestination.y()) ||
384 (ydir == 0))
385 {
386 m_xySpeed.setY(0);
387 }
388
389 SetRedraw();
390
391 if (m_xySpeed.x() == 0 && m_xySpeed.y() == 0)
392 {
393 m_moving = false;
394 emit FinishedMoving();
395 }
396
397 m_area.moveTopLeft(curXY);
398}
399
406{
407 if (!GetPainter()->SupportsAlpha() ||
408 !GetPainter()->SupportsAnimation())
409 return;
410
411 if (m_alphaChangeMode == 0)
412 return;
413
415
417
418 // Reached limits so change direction
420 {
421 if (m_alphaChangeMode == 2)
422 {
423 m_alphaChange *= -1;
424 }
425 else
426 {
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
460int MythUIType::CalcAlpha(int alphamod) const
461{
462 return (int)(m_effects.m_alpha * (alphamod / 255.0));
463}
464
465void MythUIType::DrawSelf(MythPainter * /*p*/, int /*xoffset*/, int /*yoffset*/,
466 int /*alphaMod*/, QRect /*clipRect*/)
467{
468}
469
470void 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 {
509 font.SetFace(QFont("Droid Sans"));
511 font.SetPointSize(8);
512 p->DrawText(realArea, objectName(), 0, font, 255, realArea);
513 }
514 }
515
516 p->PopTransformation();
517}
518
519void MythUIType::SetPosition(int x, int y)
520{
521 SetPosition(MythPoint(x, y));
522}
523
524void MythUIType::SetPosition(QPoint point)
525{
526 SetPosition(MythPoint(point));
527}
528
530{
531 MythPoint pos(point);
532
533 if (m_parent)
535 else
536 pos.CalculatePoint(GetMythMainWindow()->GetUIScreenRect());
537
538 if (m_area.topLeft() == pos)
539 return;
540
541 m_dirtyRegion = QRegion(m_area.toQRect());
542
543 m_area.moveTopLeft(pos);
544
545 RecalculateArea(false);
546
547 SetRedraw();
548}
549
551{
552 return m_area.topLeft();
553}
554
555void MythUIType::SetSize(const QSize size)
556{
557 if (size == m_area.size())
558 return;
559
560 m_dirtyRegion = QRegion(m_area.toQRect());
561
562 m_area.setSize(size);
564
565 if (m_parent)
567
568 SetRedraw();
569}
570
577{
578 MythPoint point(minsize);
579
580 if (m_parent)
582
583 m_minSize = point;
584
585 SetRedraw();
586}
587
588QSize MythUIType::GetMinSize(void) const
589{
590 if (!m_minSize.isValid())
591 return m_area.size();
592
593 return {m_minSize.x(), m_minSize.y()};
594}
595
597{
598 if (rect == m_area)
599 return;
600
601 m_dirtyRegion = QRegion(m_area.toQRect());
602
603 m_area = rect;
605
606 if (m_parent)
608
609 SetRedraw();
610}
611
615void MythUIType::AdjustMinArea(int delta_x, int delta_y,
616 int delta_w, int delta_h)
617{
618 // If a minsize is not set, don't use MinArea
619 if (!m_minSize.isValid())
620 return;
621
622 // Delta's are negative values; knock down the area
623 QRect bounded(m_area.x() - delta_x,
624 m_area.y() - delta_y,
625 m_area.width() + delta_w,
626 m_area.height() + delta_h);
627
628 // Make sure we have not violated the min size
629 if (!bounded.isNull() || !m_vanish)
630 {
631 QPoint center = bounded.center();
632
633 if (bounded.isNull())
634 bounded.setSize(GetMinSize());
635 else
636 bounded.setSize(bounded.size().expandedTo(GetMinSize()));
637
638 bounded.moveCenter(center);
639 }
640
641 if (bounded.x() + bounded.width() > m_area.x() + m_area.width())
642 bounded.moveRight(m_area.x() + m_area.width());
643 if (bounded.y() + bounded.height() > m_area.y() + m_area.height())
644 bounded.moveBottom(m_area.y() + m_area.height());
645 if (bounded.x() < m_area.x())
646 {
647 bounded.moveLeft(m_area.x());
648 if (bounded.width() > m_area.width())
649 bounded.setWidth(m_area.width());
650 }
651 if (bounded.y() < m_area.y())
652 {
653 bounded.moveTop(m_area.y());
654 if (bounded.height() > m_area.height())
655 bounded.setHeight(m_area.height());
656 }
657
658 m_minArea = bounded;
659 m_vanished = false;
660
661 QList<MythUIType *>::iterator it;
662
663 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
664 {
665 if (!(*it)->m_initiator)
666 (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h);
667 }
668}
669
671{
672 if (!m_minSize.isValid() || !m_vanish)
673 return;
674
679 m_vanished = true;
680
681 QList<MythUIType *>::iterator it;
682
683 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
684 {
685 if (!(*it)->m_initiator)
686 (*it)->VanishSibling();
687 }
688}
689
693void MythUIType::SetMinAreaParent(MythRect actual_area, MythRect allowed_area,
694 MythUIType *calling_child)
695{
696 int delta_x = 0;
697 int delta_y = 0;
698 int delta_w = 0;
699 int delta_h = 0;
700 MythRect area;
701
702 // If a minsize is not set, don't use MinArea
703 if (!m_minSize.isValid())
704 return;
705
706 if (calling_child->m_vanished)
707 {
708 actual_area.moveLeft(0);
709 actual_area.moveTop(0);
710 allowed_area.moveLeft(0);
711 allowed_area.moveTop(0);
712 }
713
714 actual_area.translate(m_area.x(), m_area.y());
715 allowed_area.translate(m_area.x(), m_area.y());
716
717 QList<MythUIType *>::iterator it;
718
719 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
720 {
721 if (*it == calling_child || !(*it)->m_initiator)
722 continue;
723
724 if (!(*it)->m_vanished)
725 {
726 // Find union of area(s)
727 area = (*it)->GetArea();
728 area.translate(m_area.x(), m_area.y());
729 actual_area = actual_area.united(area);
730
731 area = (*it)->m_area;
732 area.translate(m_area.x(), m_area.y());
733 allowed_area = allowed_area.united(area);
734 }
735 }
736
737 // Make sure it is not larger than the area allowed
738 actual_area = actual_area.intersected(m_area);
739 allowed_area = allowed_area.intersected(m_area);
740
741 if (m_vanish && actual_area.size().isNull())
742 {
743 m_vanished = true;
744 }
745 else
746 {
747 if (calling_child->m_vanished)
748 {
749 delta_x = m_area.x() - actual_area.x();
750 delta_y = m_area.y() - actual_area.y();
751 delta_w = actual_area.width() - m_area.width();
752 delta_h = actual_area.height() - m_area.height();
753 }
754 else
755 {
756 delta_x = allowed_area.x() - actual_area.x();
757 delta_y = allowed_area.y() - actual_area.y();
758 delta_w = actual_area.width() - allowed_area.width();
759 delta_h = actual_area.height() - allowed_area.height();
760 }
761
762 m_vanished = false;
763 }
764
765 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
766 {
767 if (*it == calling_child)
768 continue;
769
770 if (!(*it)->m_initiator)
771 {
772 if (m_vanished)
773 (*it)->VanishSibling();
774 else
775 (*it)->AdjustMinArea(delta_x, delta_y, delta_w, delta_h);
776 }
777
778 area = (*it)->GetArea();
779 area.translate(m_area.topLeft());
780 actual_area = actual_area.united(area);
781 }
782
783 if (m_vanished)
784 {
785 m_minArea.setRect(0, 0, 0, 0);
786 actual_area.setRect(0, 0, 0, 0);
787 }
788 else
789 {
790 QSize bound(actual_area.width(), actual_area.height());
791
792 bound = bound.expandedTo(GetMinSize());
793 m_minArea.setRect(actual_area.x(),
794 actual_area.y(),
795 actual_area.x() + bound.width(),
796 actual_area.y() + bound.height());
797 }
798
799 if (m_parent)
800 m_parent->SetMinAreaParent(actual_area, m_area, this);
801}
802
807{
808 // If a minsize is not set, don't use MinArea
809 if (!m_initiator || !m_minSize.isValid())
810 return;
811
812 QRect bounded(rect);
813 bool vanish = (m_vanish && rect.isNull());
814
815 if (vanish)
816 {
817 bounded.moveLeft(0);
818 bounded.moveTop(0);
819 }
820 else
821 {
822 QPoint center = bounded.center();
823
824 if (bounded.isNull())
825 bounded.setSize(GetMinSize());
826 else
827 bounded.setSize(bounded.size().expandedTo(GetMinSize()));
828
829 bounded.moveCenter(center);
830 if (bounded.x() + bounded.width() > m_area.x() + m_area.width())
831 bounded.moveRight(m_area.x() + m_area.width());
832 if (bounded.y() + bounded.height() > m_area.y() + m_area.height())
833 bounded.moveBottom(m_area.y() + m_area.height());
834 if (bounded.x() < m_area.x())
835 {
836 bounded.moveLeft(m_area.x());
837 if (bounded.width() > m_area.width())
838 bounded.setWidth(m_area.width());
839 }
840 if (bounded.y() < m_area.y())
841 {
842 bounded.moveTop(m_area.y());
843 if (bounded.height() > m_area.height())
844 bounded.setHeight(m_area.height());
845 }
846 }
847
848 m_minArea = bounded;
849 m_vanished = vanish;
850
851 if (m_parent)
853}
854
855void MythUIType::ExpandArea(const QRect rect)
856{
857 QSize childSize = rect.size();
858 QSize size = m_area.size();
859
860 if (childSize == size)
861 return;
862
863 SetSize(size.expandedTo(childSize));
864 SetRedraw();
865}
866
872{
873 if (m_vanished || m_minArea.isValid())
874 return m_minArea;
875
876 return m_area;
877}
878
880{
881 return m_area;
882}
883
884QRegion MythUIType::GetDirtyArea(void) const
885{
886 return m_dirtyRegion;
887}
888
889bool MythUIType::IsVisible(bool recurse) const
890{
891 if (recurse)
892 {
893 if (m_parent && !m_parent->IsVisible(recurse))
894 return false;
895 }
896
897 return m_visible;
898}
899
900void MythUIType::MoveTo(QPoint destXY, QPoint speedXY)
901{
902 if (!GetPainter()->SupportsAnimation())
903 return;
904
905 if (destXY.x() == m_area.x() && destXY.y() == m_area.y())
906 return;
907
908 m_moving = true;
909
910 m_xyDestination = destXY;
911 m_xySpeed = speedXY;
912}
913
914void MythUIType::AdjustAlpha(int mode, int alphachange, int minalpha,
915 int maxalpha)
916{
917 if (!GetPainter()->SupportsAlpha())
918 return;
919
920 m_alphaChangeMode = mode;
921 m_alphaChange = alphachange;
922 m_alphaMin = minalpha;
923 m_alphaMax = maxalpha;
924
926}
927
928void MythUIType::SetAlpha(int newalpha)
929{
930 if (m_effects.m_alpha == newalpha)
931 return;
932
933 m_effects.m_alpha = newalpha;
934 SetRedraw();
935}
936
937int MythUIType::GetAlpha(void) const
938{
939 return m_effects.m_alpha;
940}
941
943{
944 m_effects.m_centre = centre;
945}
946
947void MythUIType::SetZoom(float zoom)
948{
949 SetHorizontalZoom(zoom);
950 SetVerticalZoom(zoom);
951}
952
954{
955 m_effects.m_hzoom = zoom;
956 SetRedraw();
957}
958
960{
961 m_effects.m_vzoom = zoom;
962 SetRedraw();
963}
964
965void MythUIType::SetAngle(float angle)
966{
967 m_effects.m_angle = angle;
968 SetRedraw();
969}
970
975bool MythUIType::keyPressEvent(QKeyEvent * /*event*/)
976{
977 return false;
978}
979
984bool MythUIType::inputMethodEvent(QInputMethodEvent * /*event*/)
985{
986 return false;
987}
988
989void MythUIType::customEvent(QEvent *event)
990{
991 QObject::customEvent(event);
992}
993
1000{
1001 return false;
1002}
1003
1009{
1010}
1011
1013{
1014 if (!m_canHaveFocus || !m_hasFocus)
1015 return;
1016
1017 emit LosingFocus();
1018 m_hasFocus = false;
1019 Refresh();
1020}
1021
1023{
1024 if (!m_canHaveFocus || m_hasFocus)
1025 return false;
1026
1027 m_hasFocus = true;
1028 Refresh();
1029 emit TakingFocus();
1030 return true;
1031}
1032
1033void MythUIType::SetFocusedName(const QString & widgetname)
1034{
1035 m_focusedName = widgetname;
1036 emit RequestUpdate();
1037}
1038
1040{
1041}
1042
1044{
1045 SetRedraw();
1046}
1047
1048void MythUIType::UpdateDependState(MythUIType *dependee, bool isDefault)
1049{
1050 bool visible = false;
1051
1052 if (dependee)
1053 {
1054 bool reverse = m_reverseDepend[dependee];
1055 visible = reverse ? !isDefault : isDefault;
1056 // NOLINTNEXTLINE(modernize-loop-convert)
1057 for (int i = 0; i < m_dependsValue.size(); i++)
1058 {
1059 if (m_dependsValue[i].first != dependee)
1060 continue;
1061 m_dependsValue[i].second = visible;
1062 break;
1063 }
1064 }
1065
1066 if (!m_dependsValue.empty())
1067 visible = m_dependsValue[0].second;
1068 for (int i = 1; i < m_dependsValue.size(); i++)
1069 {
1070 bool v = m_dependsValue[i].second;
1071
1072 if (((i-1) < m_dependOperator.size()) &&
1073 m_dependOperator[i-1] == 1)
1074 {
1075 // OR operator
1076 visible = visible && v;
1077 }
1078 else
1079 {
1080 // AND operator
1081 visible = visible || v;
1082 }
1083 }
1084
1085 m_isDependDefault = visible;
1086
1088}
1089
1091{
1092 auto *dependee = qobject_cast<MythUIType*>(sender());
1093
1094 UpdateDependState(dependee, isDefault);
1095}
1096
1097void MythUIType::SetVisible(bool visible)
1098{
1099 if (visible == m_visible)
1100 return;
1101
1102 if (visible && m_isDependDefault)
1103 return;
1104
1105 m_visible = visible;
1106 SetRedraw();
1107
1108 if (m_visible)
1109 emit Showing();
1110 else
1111 emit Hiding();
1113}
1114
1116{
1117 m_isDependDefault = isDefault;
1118}
1119
1120void MythUIType::SetEnabled(bool enable)
1121{
1122 if (m_enabled != enable)
1123 m_enabled = enable;
1124
1125 if (enable)
1126 emit Enabling();
1127 else
1128 emit Disabling();
1129}
1130
1132{
1133 SetVisible(false);
1134}
1135
1137{
1138 SetVisible(true);
1139}
1140
1142{
1143 if (m_canHaveFocus)
1144 focusList.insert(m_focusOrder, this);
1145
1146 for (auto *child : std::ranges::reverse_view(m_childrenList))
1147 child->AddFocusableChildrenToList(focusList);
1148}
1149
1150int MythUIType::NormX(const int width)
1151{
1152 return GetMythMainWindow()->NormX(width);
1153}
1154
1155int MythUIType::NormY(const int height)
1156{
1157 return GetMythMainWindow()->NormY(height);
1158}
1159
1164{
1165 m_xmlName = base->m_xmlName;
1167 m_visible = base->m_visible;
1168 m_enabled = base->m_enabled;
1170 m_focusOrder = base->m_focusOrder;
1171
1172 m_area = base->m_area;
1174
1176 m_minSize = base->m_minSize;
1177 m_vanish = base->m_vanish;
1178 m_vanished = false;
1179 m_effects = base->m_effects;
1182 m_alphaMin = base->m_alphaMin;
1183 m_alphaMax = base->m_alphaMax;
1184
1185 m_moving = base->m_moving;
1187 m_xySpeed = base->m_xySpeed;
1188 m_deferload = base->m_deferload;
1189
1190 QList<MythUIAnimation*>::Iterator i;
1191 for (i = base->m_animations.begin(); i != base->m_animations.end(); ++i)
1192 {
1193 auto* animation = new MythUIAnimation(this);
1194 animation->CopyFrom(*i);
1195 m_animations.push_back(animation);
1196 }
1197
1198 QList<MythUIType *>::Iterator it;
1199
1200 for (it = base->m_childrenList.begin(); it != base->m_childrenList.end();
1201 ++it)
1202 {
1203 MythUIType *child = GetChild((*it)->objectName());
1204
1205 if (child)
1206 child->CopyFrom(*it);
1207 else
1208 (*it)->CreateCopy(this);
1209 }
1210
1211 m_dependsMap = base->m_dependsMap;
1212
1213 SetMinArea(base->m_minArea);
1214}
1215
1221{
1222 // Calling CreateCopy on base type is not valid
1223}
1224
1230 const QString &filename, QDomElement &element, bool showWarnings)
1231{
1232 //FIXME add movement etc.
1233
1234 if (element.tagName() == "position")
1235 SetPosition(parsePoint(element));
1236 else if (element.tagName() == "area")
1237 {
1238 SetArea(parseRect(element));
1239 }
1240 else if (element.tagName() == "minsize")
1241 {
1242 // Use parsePoint so percentages can be used
1243 if (element.hasAttribute("initiator"))
1244 m_enableInitiator = parseBool(element.attribute("initiator"));
1245
1246 if (element.hasAttribute("vanish"))
1247 m_vanish = parseBool(element.attribute("vanish"));
1248
1249 SetMinSize(parsePoint(element));
1250 }
1251 else if (element.tagName() == "alpha")
1252 {
1253 m_effects.m_alpha = getFirstText(element).toInt();
1255 }
1256 else if (element.tagName() == "alphapulse")
1257 {
1259 m_alphaMin = element.attribute("min", "0").toInt();
1260 m_effects.m_alpha = m_alphaMax = element.attribute("max", "255").toInt();
1261
1262 if (m_alphaMax > 255)
1264
1265 m_alphaMin = std::max(m_alphaMin, 0);
1266
1267 m_alphaChange = element.attribute("change", "5").toInt();
1268 }
1269 else if (element.tagName() == "focusorder")
1270 {
1271 int order = getFirstText(element).toInt();
1272 SetFocusOrder(order);
1273 }
1274 else if (element.tagName() == "loadondemand")
1275 {
1276 SetDeferLoad(parseBool(element));
1277 }
1278 else if (element.tagName() == "helptext")
1279 {
1280 m_helptext = getFirstText(element);
1281 }
1282 else if (element.tagName() == "animation")
1283 {
1284 MythUIAnimation::ParseElement(element, this);
1285 }
1286 else {
1287 if (showWarnings) {
1288 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
1289 QString("Unknown widget type '%1'").arg(element.tagName()));
1290 }
1291 return false;
1292 }
1293
1294 return true;
1295}
1296
1305{
1306}
1307
1308MythFontProperties *MythUIType::GetFont(const QString &text) const
1309{
1310 MythFontProperties *ret = m_fonts->GetFont(text);
1311
1312 if (!ret && m_parent)
1313 return m_parent->GetFont(text);
1314
1315 return ret;
1316}
1317
1319{
1320 return m_fonts->AddFont(text, fontProp);
1321}
1322
1324{
1325 if (m_parent)
1327 else
1328 m_area.CalculateArea(GetMythMainWindow()->GetUIScreenRect());
1329
1330 if (recurse)
1331 {
1332 QList<MythUIType *>::iterator it;
1333
1334 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
1335 {
1336 (*it)->RecalculateArea(recurse);
1337 }
1338 }
1339}
1340
1342{
1343 m_focusOrder = order;
1344}
1345
1347{
1348 if (!child)
1349 return false;
1350
1351 int i = m_childrenList.indexOf(child);
1352
1353 if (i != -1 || i != m_childrenList.size() - 1)
1354 {
1355 m_childrenList.removeAt(i);
1356 m_childrenList.append(child);
1357 child->SetRedraw();
1358 return true;
1359 }
1360
1361 return false;
1362}
1363
1364
1366{
1367 if (m_parent)
1368 {
1369 return m_parent->MoveChildToTop(this);
1370 }
1371
1372 return false;
1373}
1374
1375bool MythUIType::IsDeferredLoading(bool recurse) const
1376{
1377 if (m_deferload)
1378 return true;
1379
1380 if (recurse && m_parent)
1381 return m_parent->IsDeferredLoading(recurse);
1382
1383 return false;
1384}
1385
1392{
1393 QList<MythUIType *>::Iterator it;
1394
1395 for (it = m_childrenList.begin(); it != m_childrenList.end(); ++it)
1396 (*it)->LoadNow();
1397}
1398
1404bool MythUIType::ContainsPoint(const QPoint point) const
1405{
1406 return m_area.contains(point);
1407}
1408
1410{
1411 if (m_painter)
1412 return m_painter;
1413
1414 if (m_parent)
1415 return m_parent->GetPainter();
1416
1417 return GetMythPainter();
1418}
1419
1420void MythUIType::SetDependsMap(QMap<QString, QString> dependsMap)
1421{
1422 m_dependsMap = std::move(dependsMap);
1423}
1424
1426{
1427 m_reverseDepend.insert(dependee, reverse);
1428}
1429
1431{
1432 QStringList dependees;
1433 QList<int> operators;
1434 for (auto it = m_dependsMap.begin(); it != m_dependsMap.end(); ++it)
1435 {
1436 // build list of operators and dependeees.
1437 dependees.clear();
1438 operators.clear();
1439 QString& name = it.value();
1440 QStringList tmp1 = name.split("&");
1441 for (const QString& t1 : std::as_const(tmp1))
1442 {
1443 QStringList tmp2 = t1.split("|");
1444
1445 dependees.append(tmp2[0]);
1446 for (int j = 1; j < tmp2.size(); j++)
1447 {
1448 dependees.append(tmp2[j]);
1449 operators.append(1); // 1 is OR
1450 }
1451 operators.append(2); // 2 is AND
1452 }
1453
1454 MythUIType *dependant = GetChild(it.key());
1455 if (dependant)
1456 {
1457 dependant->m_dependOperator = operators;
1458 for (QString dependeeName : std::as_const(dependees))
1459 {
1460 bool reverse = false;
1461 if (dependeeName.startsWith('!'))
1462 {
1463 reverse = true;
1464 dependeeName.remove(0,1);
1465 }
1466 MythUIType *dependee = GetChild(dependeeName);
1467
1468 if (dependee)
1469 {
1470 QObject::connect(dependee, &MythUIType::DependChanged,
1471 dependant, qOverload<bool>(&MythUIType::UpdateDependState));
1472 dependant->SetReverseDependence(dependee, reverse);
1473 dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, false));
1474 dependant->UpdateDependState(dependee, true);
1475 }
1476 else
1477 {
1478 dependant->m_dependsValue.append(QPair<MythUIType *, bool>(dependee, !reverse));
1479 dependant->UpdateDependState(dependee, reverse);
1480 }
1481 }
1482 }
1483 }
1484
1485 if (recurse)
1486 {
1487 QList<MythUIType *>::iterator child;
1488 for (child = m_childrenList.begin(); child != m_childrenList.end(); ++child)
1489 {
1490 if (*child)
1491 (*child)->ConnectDependants(recurse);
1492 }
1493 }
1494}
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:97
bool IsEnabled(void) const
Definition: mythuitype.h:130
bool m_enableInitiator
Definition: mythuitype.h:278
void SetZoom(float zoom)
Definition: mythuitype.cpp:947
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:188
int m_focusOrder
Definition: mythuitype.h:286
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:348
void SetDependsMap(QMap< QString, QString > dependsMap)
virtual QRegion GetDirtyArea(void) const
Definition: mythuitype.cpp:884
bool IsVisible(bool recurse=false) const
Definition: mythuitype.cpp:889
virtual void SetSize(QSize size)
Definition: mythuitype.cpp:555
bool m_initiator
Definition: mythuitype.h:279
void VisibilityChanged(bool Visible)
void TakingFocus(void)
bool m_moving
Definition: mythuitype.h:302
void HandleMovementPulse()
Handle one frame of a movement animation.
Definition: mythuitype.cpp:358
void AddChild(MythUIType *child)
Add a child UIType.
Definition: mythuitype.cpp:81
void Hiding(void)
int m_alphaMax
Definition: mythuitype.h:300
MythRect m_minArea
Definition: mythuitype.h:289
void ActivateAnimations(MythUIAnimation::Trigger trigger)
Definition: mythuitype.cpp:274
bool m_vanished
Definition: mythuitype.h:281
void RequestUpdate(void)
void SetFocusOrder(int order)
UIEffects m_effects
Definition: mythuitype.h:295
virtual void mediaEvent(MythMediaEvent *event)
Media/Device status event handler, received from MythMediaMonitor.
void customEvent(QEvent *event) override
Definition: mythuitype.cpp:989
virtual void DrawSelf(MythPainter *p, int xoffset, int yoffset, int alphaMod, QRect clipRect)
Definition: mythuitype.cpp:465
virtual void VanishSibling(void)
Definition: mythuitype.cpp:670
void Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod=255, QRect clipRect=QRect())
Definition: mythuitype.cpp:470
bool CanTakeFocus(void) const
Return if this widget can accept input focus.
Definition: mythuitype.cpp:340
virtual void SetVisible(bool visible)
virtual MythPainter * GetPainter(void)
int m_alphaChangeMode
Definition: mythuitype.h:297
bool m_isDependDefault
Definition: mythuitype.h:282
QPoint m_xyDestination
Definition: mythuitype.h:303
QString m_xmlName
Definition: mythuitype.h:314
void AdjustAlpha(int mode, int alphachange, int minalpha=0, int maxalpha=255)
Definition: mythuitype.cpp:914
void Activate(void)
virtual void SetArea(const MythRect &rect)
Definition: mythuitype.cpp:596
void Disabling(void)
virtual void LoadNow(void)
Cause images in this and child widgets to be loaded.
bool m_vanish
Definition: mythuitype.h:280
virtual bool gestureEvent(MythGestureEvent *event)
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop.
Definition: mythuitype.cpp:999
void ExpandArea(QRect rect)
Definition: mythuitype.cpp:855
virtual QSize GetMinSize(void) const
Definition: mythuitype.cpp:588
MythUIType(QObject *parent, const QString &name)
Definition: mythuitype.cpp:42
void LoseFocus(void)
QPoint m_xySpeed
Definition: mythuitype.h:304
virtual void AdjustMinArea(int delta_x, int delta_y, int delta_w, int delta_h)
Adjust the size of a sibling.
Definition: mythuitype.cpp:615
bool m_needsRedraw
Definition: mythuitype.h:293
QList< int > m_dependOperator
Definition: mythuitype.h:272
MythPoint m_minSize
Definition: mythuitype.h:290
QMap< MythUIType *, bool > m_reverseDepend
Definition: mythuitype.h:283
void SetEnabled(bool enable)
void SetAngle(float angle)
Definition: mythuitype.cpp:965
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:284
MythUIType * GetChildAt(QPoint p, bool recursive=true, bool focusable=true) const
Return the first MythUIType at the given coordinates.
Definition: mythuitype.cpp:227
void ResetNeedsRedraw(void)
Definition: mythuitype.cpp:289
void SetRedraw(void)
Definition: mythuitype.cpp:299
bool TakeFocus(void)
void Enabling(void)
void SetFocusedName(const QString &widgetname)
void ConnectDependants(bool recurse=false)
void SetVerticalZoom(float zoom)
Definition: mythuitype.cpp:959
virtual void SetMinArea(const MythRect &rect)
Set the minimum area based on the given size.
Definition: mythuitype.cpp:806
virtual void Pulse(void)
Pulse is called 70 times a second to trigger a single frame of an animation.
Definition: mythuitype.cpp:442
void Hide(void)
void SetChildNeedsRedraw(MythUIType *child)
Definition: mythuitype.cpp:315
FontMap * m_fonts
Definition: mythuitype.h:306
static int NormY(int height)
MythFontProperties * GetFont(const QString &text) const
void Refresh(void)
QString m_xmlLocation
Definition: mythuitype.h:315
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:871
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:308
bool m_canHaveFocus
Definition: mythuitype.h:276
void SetDependIsDefault(bool isDefault)
~MythUIType() override
Definition: mythuitype.cpp:61
QMap< QString, QString > m_dependsMap
Definition: mythuitype.h:267
bool m_enabled
Definition: mythuitype.h:277
virtual MythRect GetFullArea(void) const
Definition: mythuitype.cpp:879
int m_alphaMin
Definition: mythuitype.h:299
bool m_hasFocus
Definition: mythuitype.h:275
void DeleteAllChildren(void)
Delete all child widgets.
Definition: mythuitype.cpp:208
QString m_focusedName
Definition: mythuitype.h:285
int CalcAlpha(int alphamod) const
Definition: mythuitype.cpp:460
bool m_visible
Definition: mythuitype.h:274
virtual void SetMinAreaParent(MythRect actual_area, MythRect allowed_area, MythUIType *child)
Adjust the size of sibling objects within the button.
Definition: mythuitype.cpp:693
MythPainter * m_painter
Definition: mythuitype.h:309
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:311
void UpdateDependState(bool isDefault)
void HandleAlphaPulse()
Handle one frame of an alpha (transparency) change animation.
Definition: mythuitype.cpp:405
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:130
bool MoveToTop(void)
void SetAlpha(int newalpha)
Definition: mythuitype.cpp:928
void SetCentre(UIEffects::Centre centre)
Definition: mythuitype.cpp:942
void MoveTo(QPoint destXY, QPoint speedXY)
Definition: mythuitype.cpp:900
virtual bool inputMethodEvent(QInputMethodEvent *event)
Input Method event handler.
Definition: mythuitype.cpp:984
void DeleteChild(const QString &name)
Delete a named child of this UIType.
Definition: mythuitype.cpp:145
void SetHorizontalZoom(float zoom)
Definition: mythuitype.cpp:953
QColor m_borderColor
Definition: mythuitype.h:319
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:71
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:266
void FinishedFading(void)
static int NormX(int width)
void SetDeferLoad(bool defer)
Definition: mythuitype.h:199
virtual void SetMinSize(const MythPoint &size)
Set the minimum size of this widget, for widgets which can be rescaled.
Definition: mythuitype.cpp:576
virtual bool keyPressEvent(QKeyEvent *event)
Key event handler.
Definition: mythuitype.cpp:975
MythRect m_area
Definition: mythuitype.h:288
QList< MythUIType * > GetAllDescendants(void)
Definition: mythuitype.cpp:193
int m_alphaChange
Definition: mythuitype.h:298
virtual MythPoint GetPosition(void) const
Definition: mythuitype.cpp:550
QRegion m_dirtyRegion
Definition: mythuitype.h:292
QList< QPair< MythUIType *, bool > > m_dependsValue
Definition: mythuitype.h:271
QString m_helptext
Definition: mythuitype.h:312
void LosingFocus(void)
bool m_deferload
Definition: mythuitype.h:317
int GetAlpha(void) const
Definition: mythuitype.cpp:937
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:89
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:201
#define VERBOSE_XML(type, level, filename, element, msg)
Definition: xmlparsebase.h:15