MythTV master
guidegrid.cpp
Go to the documentation of this file.
1// C/C++
2#include <algorithm>
3#include <cstdint> // for uint64_t
4#include <deque> // for _Deque_iterator, operator!=, etc
5
6// Qt
7#include <QCoreApplication>
8#include <QDateTime>
9#include <QKeyEvent>
10
11// MythTV
12#include "libmythbase/autodeletedeque.h" // for AutoDeleteDeque, etc
16#include "libmythbase/mythevent.h" // for MythEvent, etc
18#include "libmythbase/mythtypes.h" // for InfoMap
19#include "libmythtv/cardutil.h"
26#include "libmythtv/tv.h" // for ::kState_WatchingLiveTV
27#include "libmythtv/tv_actions.h" // for ACTION_CHANNELSEARCH, etc
28#include "libmythtv/tv_play.h"
32#include "libmythui/mythmainwindow.h" // for GetMythMainWindow, etc
33#include "libmythui/mythrect.h" // for MythRect
34#include "libmythui/mythscreenstack.h" // for MythScreenStack
35#include "libmythui/mythscreentype.h" // for MythScreenType
36#include "libmythui/mythuiactions.h" // for ACTION_SELECT, ACTION_DOWN, etc
42#include "libmythui/mythuiutils.h" // for UIUtilW, UIUtilE
43
44// MythFrontend
45#include "guidegrid.h"
46#include "progfind.h"
47
48QWaitCondition epgIsVisibleCond;
49
50#define LOC QString("GuideGrid: ")
51#define LOC_ERR QString("GuideGrid, Error: ")
52#define LOC_WARN QString("GuideGrid, Warning: ")
53
54const QString kUnknownTitle = "";
55//const QString kUnknownCategory = QObject::tr("Unknown");
56static constexpr std::chrono::milliseconds kUpdateMS { 60s }; // Grid update interval
57static constexpr int64_t kFourMinutes { 4LL * 60 };
58static constexpr int64_t kFiveMinutes { 5LL * 60 };
59static constexpr int64_t kThirtyMinutes { 30LL * 60 };
60static constexpr int64_t kEightHours { 8 * 60LL * 60 };
61static constexpr int64_t kOneDay { 24 * 60LL * 60 };
62static bool SelectionIsTunable(const ChannelInfoList &selection);
63
65 JumpToChannelListener *parent, QString start_entry,
66 int start_chan_idx, int cur_chan_idx, uint rows_disp) :
67 m_listener(parent),
68 m_entry(std::move(start_entry)),
69 m_previousStartChannelIndex(start_chan_idx),
70 m_previousCurrentChannelIndex(cur_chan_idx),
71 m_rowsDisplayed(rows_disp),
72 m_timer(new QTimer(this))
73{
74 if (parent && m_timer)
75 {
77 m_timer->setSingleShot(true);
78 }
79 Update();
80}
81
82
84{
85 if (m_listener)
86 {
88 m_listener = nullptr;
89 }
90
91 if (m_timer)
92 {
93 m_timer->stop();
94 m_timer = nullptr;
95 }
96
97 QObject::deleteLater();
98}
99
100
101static bool has_action(const QString& action, const QStringList &actions)
102{
103 QStringList::const_iterator it;
104 for (it = actions.begin(); it != actions.end(); ++it)
105 {
106 if (action == *it)
107 return true;
108 }
109 return false;
110}
111
112bool JumpToChannel::ProcessEntry(const QStringList &actions, const QKeyEvent *e)
113{
114 if (!m_listener)
115 return false;
116
117 if (has_action("ESCAPE", actions))
118 {
121 deleteLater();
122 return true;
123 }
124
125 if (has_action("DELETE", actions))
126 {
127 if (!m_entry.isEmpty())
128 m_entry = m_entry.left(m_entry.length()-1);
129 Update();
130 return true;
131 }
132
133 if (has_action(ACTION_SELECT, actions))
134 {
135 if (Update())
136 deleteLater();
137 return true;
138 }
139
140 QString txt = e->text();
141 bool isUInt = false;
142 // cppcheck-suppress ignoredReturnValue
143 txt.toUInt(&isUInt);
144 if (isUInt)
145 {
146 m_entry += txt;
147 Update();
148 return true;
149 }
150
151 if (!m_entry.isEmpty() && (txt=="_" || txt=="-" || txt=="#" || txt=="."))
152 {
153 m_entry += txt;
154 Update();
155 return true;
156 }
157
158 return false;
159}
160
162{
163 if (!m_timer || !m_listener)
164 return false;
165
166 m_timer->stop();
167
168 // find the closest channel ...
169 int i = m_listener->FindChannel(0, m_entry, false);
170 if (i >= 0)
171 {
172 // setup the timeout timer for jump mode
174
175 // rows_displayed to center
176 int start = i - (m_rowsDisplayed/2);
177 int cur = m_rowsDisplayed/2;
178 m_listener->GoTo(start, cur);
179 return true;
180 }
181
182 // prefix must be invalid.. reset entry..
184 return false;
185}
186
187// GuideStatus is used for transferring the relevant read-only data
188// from GuideGrid to the GuideUpdateProgramRow constructor.
190{
191public:
192 GuideStatus(unsigned int firstRow, unsigned int numRows,
193 QVector<int> channums,
194 const MythRect &gg_programRect,
195 int gg_channelCount,
196 QDateTime currentStartTime,
197 QDateTime currentEndTime,
198 uint currentStartChannel,
199 int currentRow, int currentCol,
200 int channelCount, int timeCount,
201 bool verticalLayout,
202 QDateTime firstTime, QDateTime lastTime)
203 : m_firstRow(firstRow), m_numRows(numRows),
204 m_chanNums(std::move(channums)),
205 m_ggProgramRect(gg_programRect), m_ggChannelCount(gg_channelCount),
206 m_currentStartTime(std::move(currentStartTime)),
207 m_currentEndTime(std::move(currentEndTime)),
208 m_currentStartChannel(currentStartChannel), m_currentRow(currentRow),
209 m_currentCol(currentCol), m_channelCount(channelCount),
210 m_timeCount(timeCount), m_verticalLayout(verticalLayout),
211 m_firstTime(std::move(firstTime)), m_lastTime(std::move(lastTime)) {}
212 const unsigned int m_firstRow, m_numRows;
213 const QVector<int> m_chanNums;
221 const QDateTime m_firstTime, m_lastTime;
222};
223
225{
226public:
227 explicit GuideUpdaterBase(GuideGrid *guide) : m_guide(guide) {}
228 virtual ~GuideUpdaterBase() = default;
229
230 // Execute the initial non-UI part (in a separate thread). Return
231 // true if ExecuteUI() should be run later, or false if the work
232 // is no longer relevant (e.g., the UI elements have scrolled
233 // offscreen by now).
234 virtual bool ExecuteNonUI(void) = 0;
235 // Execute the UI part in the UI thread.
236 virtual void ExecuteUI(void) = 0;
237
238protected:
239 GuideGrid *m_guide {nullptr};
240};
241
243{
244public:
246 QVector<ProgramList*> proglists)
247 : GuideUpdaterBase(guide),
263 m_proglists(std::move(proglists)) {}
264 ~GuideUpdateProgramRow() override = default;
265 bool ExecuteNonUI(void) override // GuideUpdaterBase
266 {
267 // Don't bother to do any work if the starting coordinates of
268 // the guide have changed while the thread was waiting to
269 // start.
272 {
273 return false;
274 }
275
276 for (unsigned int i = 0; i < m_numRows; ++i)
277 {
278 unsigned int row = i + m_firstRow;
279 if (!m_proglists[i])
280 m_proglists[i] =
284 m_proglists[i]);
285 }
286 return true;
287 }
288 void ExecuteUI(void) override // GuideUpdaterBase
289 {
293 }
294
295private:
296 void fillProgramRowInfosWith(int row, const QDateTime& start,
297 ProgramList *proglist);
298
299 const unsigned int m_firstRow;
300 const unsigned int m_numRows;
301 const QVector<int> m_chanNums;
304 const QDateTime m_currentStartTime;
305 const QDateTime m_currentEndTime;
307 const int m_currentRow;
308 const int m_currentCol;
309 const int m_channelCount;
310 const int m_timeCount;
312 const QDateTime m_firstTime;
313 const QDateTime m_lastTime;
314
315 QVector<ProgramList*> m_proglists;
317 int m_progPast {0};
318 std::list<GuideUIElement> m_result;
319};
320
322{
323public:
325 : GuideUpdaterBase(guide), m_currentStartChannel(startChan) {}
326 bool ExecuteNonUI(void) override // GuideUpdaterBase
327 {
329 return false;
331 return true;
332 }
333 void ExecuteUI(void) override // GuideUpdaterBase
334 {
336 }
338 QVector<ChannelInfo *> m_chinfos;
339 QVector<bool> m_unavailables;
340};
341
342class UpdateGuideEvent : public QEvent
343{
344public:
346 QEvent(kEventType), m_updater(updater) {}
348 static const Type kEventType;
349};
350const QEvent::Type UpdateGuideEvent::kEventType =
351 (QEvent::Type) QEvent::registerEventType();
352
353class GuideHelper : public QRunnable
354{
355public:
357 : m_guide(guide), m_updater(updater)
358 {
359 QMutexLocker locker(&s_lock);
361 }
362 void run(void) override // QRunnable
363 {
364 QThread::currentThread()->setPriority(QThread::IdlePriority);
365 if (m_updater)
366 {
367 if (m_updater->ExecuteNonUI())
368 {
369 QCoreApplication::postEvent(m_guide,
371 }
372 else
373 {
374 delete m_updater;
375 m_updater = nullptr;
376 }
377 }
378
379 QMutexLocker locker(&s_lock);
381 if (!s_loading[m_guide])
382 s_wait.wakeAll();
383 }
384 static bool IsLoading(GuideGrid *guide)
385 {
386 QMutexLocker locker(&s_lock);
387 return s_loading[guide] != 0U;
388 }
389 static void Wait(GuideGrid *guide)
390 {
391 QMutexLocker locker(&s_lock);
392 while (s_loading[guide])
393 {
394 if (!s_wait.wait(locker.mutex(), 15000UL))
395 return;
396 }
397 }
398private:
399 GuideGrid *m_guide {nullptr};
401
402 static QMutex s_lock;
403 static QWaitCondition s_wait;
404 static QHash<GuideGrid*,uint> s_loading;
405};
407QWaitCondition GuideHelper::s_wait;
408QHash<GuideGrid*,uint> GuideHelper::s_loading;
409
410void GuideGrid::RunProgramGuide(uint chanid, const QString &channum,
411 const QDateTime &startTime,
412 TV *player, bool embedVideo,
413 bool allowFinder, int changrpid)
414{
415 // which channel group should we default to
416 if (changrpid == -2)
417 changrpid = gCoreContext->GetNumSetting("ChannelGroupDefault", -1);
418
419 // check there are some channels setup
421 0, true, "", (changrpid<0) ? 0 : changrpid);
422
423 // Fallback to All Programs if the selected group does not exist or is empty
424 if (channels.empty() && changrpid != -1)
425 {
426 LOG(VB_GENERAL, LOG_WARNING, LOC +
427 QString("Channelgroup '%1' is empty, changing to 'All Programs'")
428 .arg(ChannelGroup::GetChannelGroupName(changrpid)));
429 changrpid = -1;
430 channels = ChannelUtil::GetChannels(0, true, "", 0);
431 }
432
433 if (channels.empty())
434 {
435 QString message;
436 if (changrpid == -1)
437 {
438 message = tr("You don't have any channels defined in the database."
439 "\n\t\t\tThe program guide will have nothing to show you.");
440 }
441 else
442 {
443 message = tr("Channel group '%1' doesn't have any channels defined."
444 "\n\t\t\tThe program guide will have nothing to show you.")
445 .arg(ChannelGroup::GetChannelGroupName(changrpid));
446 }
447
448 LOG(VB_GENERAL, LOG_WARNING, LOC + message);
449
450 if (!player)
451 ShowOkPopup(message);
452 else if (allowFinder)
453 emit player->RequestEmbedding(false);
454 return;
455 }
456
457 // If chanid/channum are unset, find the channel that would
458 // naturally be selected when Live TV is started. This depends on
459 // the available tuners, their capturecard.livetvorder values, and
460 // their capturecard.startchan values.
461 QString actualChannum = channum;
462 if (chanid == 0 && actualChannum.isEmpty())
463 {
464 uint defaultChanid = gCoreContext->GetNumSetting("DefaultChanid", 0);
465 if (defaultChanid && TV::IsTunable(defaultChanid))
466 chanid = defaultChanid;
467 }
468 if (chanid == 0 && actualChannum.isEmpty())
469 {
470 std::vector<unsigned int> inputIDs = RemoteRequestFreeInputList(0);
471 if (!inputIDs.empty())
472 actualChannum = CardUtil::GetStartChannel(inputIDs[0]);
473 }
474
476 auto *gg = new GuideGrid(mainStack, chanid, actualChannum, startTime,
477 player, embedVideo, allowFinder, changrpid);
478
479 if (gg->Create())
480 mainStack->AddScreen(gg, (player == nullptr));
481 else
482 delete gg;
483}
484
486 uint chanid, QString channum, const QDateTime &startTime,
487 TV *player, bool embedVideo,
488 bool allowFinder, int changrpid)
489 : ScheduleCommon(parent, "guidegrid"),
490 m_selectRecThreshold(gCoreContext->GetDurSetting<std::chrono::minutes>("SelChangeRecThreshold", 16min)),
491 m_allowFinder(allowFinder),
492 m_startChanID(chanid),
493 m_startChanNum(std::move(channum)),
494 m_sortReverse(gCoreContext->GetBoolSetting("EPGSortReverse", false)),
495 m_player(player),
496 m_embedVideo(embedVideo),
497 m_channelOrdering(gCoreContext->GetSetting("ChannelOrdering", "channum")),
498 m_updateTimer(new QTimer(this)),
499 m_threadPool("GuideGridHelperPool"),
500 m_changrpid(changrpid),
501 m_changrplist(ChannelGroup::GetChannelGroups(false)),
502 m_channelGroupListManual(ChannelGroup::GetManualChannelGroups(true))
503{
505
506 m_programs.resize(MAX_DISPLAY_CHANS, nullptr);
507
509 if (startTime.isValid() &&
510 startTime > m_originalStartTime.addSecs(-kEightHours))
511 m_originalStartTime = startTime;
512
513 int secsoffset = -(((m_originalStartTime.time().minute() % 30) * 60) +
514 m_originalStartTime.time().second());
515 m_currentStartTime = m_originalStartTime.addSecs(secsoffset);
517
518 if (m_player)
519 {
520 m_player->IncrRef();
524 }
525}
526
528{
529 if (Player && (Player == m_player))
530 {
531 emit m_player->RequestEmbedding(false);
532 HideTVWindow();
533 m_player->DecrRef();
534 m_player = nullptr;
535 }
536}
537
539{
540 QString windowName = "programguide";
541
542 if (m_embedVideo)
543 windowName = "programguide-video";
544
545 if (!LoadWindowFromXML("schedule-ui.xml", windowName, this))
546 return false;
547
548 bool err = false;
549 UIUtilE::Assign(this, m_timeList, "timelist", &err);
550 UIUtilE::Assign(this, m_channelList, "channellist", &err);
551 UIUtilE::Assign(this, m_guideGrid, "guidegrid", &err);
552 UIUtilW::Assign(this, m_dateText, "datetext");
553 UIUtilW::Assign(this, m_longdateText, "longdatetext");
554 UIUtilW::Assign(this, m_changroupname, "channelgroup");
555 UIUtilW::Assign(this, m_channelImage, "channelicon");
556 UIUtilW::Assign(this, m_jumpToText, "jumptotext");
557
558 if (err)
559 {
560 LOG(VB_GENERAL, LOG_ERR,
561 QString("Cannot load screen '%1'").arg(windowName));
562 return false;
563 }
564
566
567 MythUIImage *videoImage = dynamic_cast<MythUIImage *>(GetChild("video"));
568 if (videoImage && m_embedVideo)
569 m_videoRect = videoImage->GetArea();
570 else
571 m_videoRect = QRect(0,0,0,0);
572
576
578
580 return true;
581}
582
584{
587
589 int maxchannel = GetChannelCount();
590 m_channelCount = std::min(m_channelCount, maxchannel);
591
592 for (int y = 0; y < m_channelCount; ++y)
593 {
594 int chanNum = y + m_currentStartChannel;
595 if (chanNum >= (int) m_channelInfos.size())
596 chanNum -= (int) m_channelInfos.size();
597 if (chanNum >= (int) m_channelInfos.size())
598 continue;
599
600 chanNum = std::max(chanNum, 0);
601
602 delete m_programs[y];
604 }
605}
606
608{
610 m_currentCol = 0;
611
613
615
616 fillProgramInfos(true);
617
618 m_updateTimer->start(kUpdateMS);
619
621
622 QString changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
623
624 if (m_changroupname)
625 m_changroupname->SetText(changrpname);
626
628}
629
631{
632 m_updateTimer->disconnect(this);
633 m_updateTimer = nullptr;
634
635 GuideHelper::Wait(this);
636
638
639 while (!m_programs.empty())
640 {
641 if (m_programs.back())
642 delete m_programs.back();
643 m_programs.pop_back();
644 }
645
646 m_channelInfos.clear();
647
648 gCoreContext->SaveSetting("EPGSortReverse", m_sortReverse ? "1" : "0");
649
650 if (m_player)
651 {
652 // if we have a player and we are returning to it we need
653 // to tell it to stop embedding and return to fullscreen
654 if (m_allowFinder)
655 emit m_player->RequestEmbedding(false);
656
657 // maybe the user selected a different channel group,
658 // tell the player to update its channel list just in case
660 m_player->DecrRef();
661 }
662
663 if (gCoreContext->GetBoolSetting("ChannelGroupRememberLast", false))
664 gCoreContext->SaveSetting("ChannelGroupDefault", m_changrpid);
665}
666
667bool GuideGrid::keyPressEvent(QKeyEvent *event)
668{
669 QStringList actions;
670 bool handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", event, actions);
671
672 if (handled)
673 return true;
674
675 if (!actions.empty())
676 {
677 QMutexLocker locker(&m_jumpToChannelLock);
678
679 if (!m_jumpToChannel)
680 {
681 const QString& chanNum = actions[0];
682 bool isNum = false;
683 (void)chanNum.toInt(&isNum);
684 if (isNum)
685 {
686 // see if we can find a matching channel before creating the JumpToChannel otherwise
687 // JumpToChannel will delete itself in the ctor leading to a segfault
688 int i = FindChannel(0, chanNum, false);
689 if (i >= 0)
690 {
691 m_jumpToChannel = new JumpToChannel(this, chanNum,
695 }
696
697 handled = true;
698 }
699 }
700
701 if (m_jumpToChannel && !handled)
702 handled = m_jumpToChannel->ProcessEntry(actions, event);
703 }
704
705 for (int i = 0; i < actions.size() && !handled; ++i)
706 {
707 const QString& action = actions[i];
708 handled = true;
709 if (action == ACTION_UP)
710 {
712 cursorLeft();
713 else
714 cursorUp();
715 }
716 else if (action == ACTION_DOWN)
717 {
719 cursorRight();
720 else
721 cursorDown();
722 }
723 else if (action == ACTION_LEFT)
724 {
726 cursorUp();
727 else
728 cursorLeft();
729 }
730 else if (action == ACTION_RIGHT)
731 {
733 cursorDown();
734 else
735 cursorRight();
736 }
737 else if (action == "PAGEUP")
738 {
741 else
743 }
744 else if (action == "PAGEDOWN")
745 {
748 else
750 }
751 else if (action == ACTION_PAGELEFT)
752 {
755 else
757 }
758 else if (action == ACTION_PAGERIGHT)
759 {
762 else
764 }
765 else if (action == ACTION_DAYLEFT)
766 {
768 }
769 else if (action == ACTION_DAYRIGHT)
770 {
772 }
773 else if (action == "NEXTFAV")
774 {
776 }
777 else if (action == ACTION_FINDER)
778 {
780 }
781 else if (action == ACTION_CHANNELSEARCH)
782 {
784 }
785 else if (action == "MENU")
786 {
787 ShowMenu();
788 }
789 else if (action == "ESCAPE" || action == ACTION_GUIDE)
790 {
791 Close();
792 }
793 else if (action == ACTION_SELECT)
794 {
795 ProgramInfo *pginfo =
797 auto secsTillStart = pginfo
800 {
801 // See if this show is far enough into the future that it's
802 // probable that the user wanted to schedule it to record
803 // instead of changing the channel.
804 if (pginfo && (pginfo->GetTitle() != kUnknownTitle) &&
805 (secsTillStart >= m_selectRecThreshold))
806 {
808 }
809 else
810 {
811 enter();
812 }
813 }
814 else
815 {
816 // Edit Recording should include "Watch this channel"
817 // is we selected a show that is current.
820 && (secsTillStart < m_selectRecThreshold));
821 }
822 }
823 else if (action == "EDIT")
824 {
826 }
827 else if (action == "CUSTOMEDIT")
828 {
829 EditCustom();
830 }
831 else if (action == "DELETE")
832 {
833 deleteRule();
834 }
835 else if (action == "UPCOMING")
836 {
837 ShowUpcoming();
838 }
839 else if (action == "PREVRECORDED")
840 {
841 ShowPrevious();
842 }
843 else if (action == "DETAILS" || action == "INFO")
844 {
845 ShowDetails();
846 }
847 else if (action == ACTION_TOGGLERECORD)
848 {
849 QuickRecord();
850 }
851 else if (action == ACTION_TOGGLEFAV)
852 {
853 if (m_changrpid == -1)
855 else
857 }
858 else if (action == "CHANUPDATE")
859 {
861 }
862 else if (action == ACTION_VOLUMEUP)
863 {
864 emit ChangeVolume(true);
865 }
866 else if (action == ACTION_VOLUMEDOWN)
867 {
868 emit ChangeVolume(false);
869 }
870 else if (action == "CYCLEAUDIOCHAN")
871 {
872 emit ToggleMute(true);
873 }
874 else if (action == ACTION_MUTEAUDIO)
875 {
876 emit ToggleMute(false);
877 }
878 else if (action == ACTION_TOGGLEPGORDER)
879 {
883 }
884 else
885 {
886 handled = false;
887 }
888 }
889
890 if (!handled && MythScreenType::keyPressEvent(event))
891 handled = true;
892
893 return handled;
894}
895
897{
898 bool handled = true;
899
900 if (!event)
901 {
902 LOG(VB_GENERAL, LOG_INFO, LOC + "Guide Gesture no event");
903 return false;
904 }
905
906 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture event %1")
907 .arg(QString::number(event->GetGesture())));
908 switch (event->GetGesture())
909 {
911 {
912 handled = false;
913
914 // We want the relative position of the click
915 QPoint position = event->GetPosition();
916 if (m_parent)
917 position -= m_parent->GetArea().topLeft();
918
919 MythUIType *type = GetChildAt(position, false, false);
920
921 if (!type)
922 return false;
923
924 auto *object = dynamic_cast<MythUIStateType *>(type);
925
926 if (object)
927 {
928 QString name = object->objectName();
929 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click name %1").arg(name));
930
931 if (name.startsWith("channellist"))
932 {
933 auto* channelList = qobject_cast<MythUIButtonList*>(object);
934
935 if (channelList)
936 {
937 handled = channelList->gestureEvent(event);
938 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click channel list %1").arg(handled));
939 }
940 }
941 else if (name.startsWith("guidegrid"))
942 {
943 auto* guidegrid = qobject_cast<MythUIGuideGrid*>(object);
944
945 if (guidegrid)
946 {
947 handled = true;
948
949 QPoint rowCol = guidegrid->GetRowAndColumn(position - guidegrid->GetArea().topLeft());
950
951 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg %1,%2 (%3,%4)")
952 .arg(rowCol.y())
953 .arg(rowCol.x())
954 .arg(m_currentRow)
955 .arg(m_currentCol)
956 );
957 if ((rowCol.y() >= 0) && (rowCol.x() >= 0))
958 {
959 if ((rowCol.y() == m_currentRow) && (rowCol.x() == m_currentCol))
960 {
962 {
963 // See if this show is far enough into the future that it's
964 // probable that the user wanted to schedule it to record
965 // instead of changing the channel.
966 ProgramInfo *pginfo =
968 auto secsTillStart = pginfo
970 if (pginfo && (pginfo->GetTitle() != kUnknownTitle) &&
971 (secsTillStart >= m_selectRecThreshold))
972 {
973 //EditRecording();
974 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg EditRec"));
975 }
976 else
977 {
978 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg enter"));
979 enter();
980 }
981 }
982 else
983 {
984 //EditRecording();
985 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg not live"));
986 }
987 }
988 else
989 {
990 bool rowChanged = (rowCol.y() != m_currentRow);
991 bool colChanged = (rowCol.x() != m_currentCol);
992 if (rowChanged)
994
995 m_currentRow = rowCol.y();
996 m_currentCol = rowCol.x();
997
999 if (colChanged)
1000 {
1001 m_currentStartTime = m_programInfos[m_currentRow][m_currentCol]->GetScheduledStartTime();
1002 fillTimeInfos();
1003 }
1004 if (rowChanged)
1006 if (colChanged)
1008 }
1009 }
1010 }
1011 }
1012
1013 }
1014 }
1015 break;
1016
1018 if (m_verticalLayout)
1019 cursorLeft();
1020 else
1021 cursorUp();
1022 break;
1023
1025 if (m_verticalLayout)
1026 cursorRight();
1027 else
1028 cursorDown();
1029 break;
1030
1032 if (m_verticalLayout)
1033 cursorUp();
1034 else
1035 cursorLeft();
1036 break;
1037
1039 if (m_verticalLayout)
1040 cursorDown();
1041 else
1042 cursorRight();
1043 break;
1044
1046 if (m_verticalLayout)
1048 else
1050 break;
1051
1053 if (m_verticalLayout)
1055 else
1057 break;
1058
1060 if (m_verticalLayout)
1062 else
1064 break;
1065
1067 if (m_verticalLayout)
1069 else
1071 break;
1072
1075 break;
1076
1079 break;
1080
1082 enter();
1083 break;
1084
1085 default:
1086 handled = false;
1087 break;
1088 }
1089
1090 if (!handled && MythScreenType::gestureEvent(event))
1091 handled = true;
1092
1093 return handled;
1094}
1095
1096static bool SelectionIsTunable(const ChannelInfoList &selection)
1097{
1098 return std::ranges::any_of(selection,
1099 [selection](const auto & chan){ return TV::IsTunable(chan.m_chanId); } );
1100}
1101
1103{
1104 QString label = tr("Guide Options");
1105
1106 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1107 auto *menuPopup = new MythDialogBox(label, popupStack, "guideMenuPopup");
1108
1109 if (menuPopup->Create())
1110 {
1111 menuPopup->SetReturnEvent(this, "guidemenu");
1112
1114 menuPopup->AddButton(tr("Change to Channel"));
1116 menuPopup->AddButton(tr("Watch This Channel"));
1117
1118 menuPopup->AddButton(tr("Record This"));
1119
1120 menuPopup->AddButton(tr("Recording Options"), nullptr, true);
1121
1122 menuPopup->AddButton(tr("Program Details"));
1123
1124 menuPopup->AddButton(tr("Jump to Time"), nullptr, true);
1125
1126 menuPopup->AddButton(tr("Reverse Channel Order"));
1127
1128 menuPopup->AddButton(tr("Channel Search"));
1129
1130 if (!m_changrplist.empty())
1131 {
1132 menuPopup->AddButton(tr("Choose Channel Group"));
1133
1135 menuPopup->AddButton(tr("Add To Channel Group"), nullptr, true);
1136 else
1137 menuPopup->AddButton(tr("Remove from Channel Group"));
1138 }
1139
1140 popupStack->AddScreen(menuPopup);
1141 }
1142 else
1143 {
1144 delete menuPopup;
1145 }
1146}
1147
1149{
1150 QString label = tr("Recording Options");
1151
1152 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1153 auto *menuPopup = new MythDialogBox(label, popupStack, "recMenuPopup");
1154
1155 if (menuPopup->Create())
1156 {
1157 menuPopup->SetReturnEvent(this, "recmenu");
1158
1160
1161 if (pginfo && pginfo->GetRecordingRuleID())
1162 menuPopup->AddButton(tr("Edit Recording Status"));
1163 menuPopup->AddButton(tr("Edit Schedule"));
1164 menuPopup->AddButton(tr("Show Upcoming"));
1165 menuPopup->AddButton(tr("Previously Recorded"));
1166 menuPopup->AddButton(tr("Custom Edit"));
1167
1168 if (pginfo && pginfo->GetRecordingRuleID())
1169 menuPopup->AddButton(tr("Delete Rule"));
1170
1171 popupStack->AddScreen(menuPopup);
1172 }
1173 else
1174 {
1175 delete menuPopup;
1176 }
1177}
1178
1180{
1181 sel = (sel >= 0) ? sel : m_channelInfoIdx[chan_idx];
1182
1183 if (chan_idx >= GetChannelCount())
1184 return nullptr;
1185
1186 if (sel >= (int) m_channelInfos[chan_idx].size())
1187 return nullptr;
1188
1189 return &(m_channelInfos[chan_idx][sel]);
1190}
1191
1192const ChannelInfo *GuideGrid::GetChannelInfo(uint chan_idx, int sel) const
1193{
1194 return ((GuideGrid*)this)->GetChannelInfo(chan_idx, sel);
1195}
1196
1198{
1199 return m_channelInfos.size();
1200}
1201
1203{
1204 uint cnt = GetChannelCount();
1205 if (!cnt)
1206 return -1;
1207
1208 row = (row < 0) ? m_currentRow : row;
1209 return (row + m_currentStartChannel) % cnt;
1210}
1211
1213{
1214 ProgramList proglist;
1215 MSqlBindings bindings;
1216 QString querystr =
1217 "WHERE program.chanid = :CHANID AND "
1218 " program.endtime >= :STARTTS AND "
1219 " program.starttime <= :ENDTS AND "
1220 " program.starttime >= :STARTLIMITTS AND "
1221 " program.manualid = 0 ";
1222 QDateTime starttime = m_currentStartTime.addSecs(0 - m_currentStartTime.time().second());
1223 bindings[":STARTTS"] = starttime;
1224 bindings[":STARTLIMITTS"] = starttime.addDays(-1);
1225 bindings[":ENDTS"] = m_currentEndTime.addSecs(0 - m_currentEndTime.time().second());
1226 bindings[":CHANID"] = chanid;
1227
1228 ProgramList dummy;
1229 LoadFromProgram(proglist, querystr, bindings, dummy, ProgGroupBy::ChanNum);
1230
1231 return proglist;
1232}
1233
1235{
1236 if (!proglist)
1237 return nullptr;
1238 auto *result = new ProgramList();
1239 // AutoDeleteDeque doesn't work with std::back_inserter
1240 for (auto & pi : *proglist)
1241 result->push_back(new ProgramInfo(*pi)); // cppcheck-suppress useStlAlgorithm
1242 return result;
1243}
1244
1246 uint chan_idx, bool with_same_channum) const
1247{
1248 uint si = m_channelInfoIdx[chan_idx];
1249 const ChannelInfo *chinfo = GetChannelInfo(chan_idx, si);
1250
1253
1254 const uint cnt = (ctx && chinfo) ? m_channelInfos[chan_idx].size() : 0;
1255 for (uint i = 0; i < cnt; ++i)
1256 {
1257 if (i == si)
1258 continue;
1259
1260 const ChannelInfo *ciinfo = GetChannelInfo(chan_idx, i);
1261 if (!ciinfo)
1262 continue;
1263
1264 bool same_channum = ciinfo->m_chanNum == chinfo->m_chanNum;
1265
1266 if (with_same_channum != same_channum)
1267 continue;
1268
1269 if (!TV::IsTunable(ciinfo->m_chanId))
1270 continue;
1271
1272 if (with_same_channum)
1273 {
1274 si = i;
1275 break;
1276 }
1277
1278 ProgramList proglist = GetProgramList(chinfo->m_chanId);
1279 ProgramList ch_proglist = GetProgramList(ciinfo->m_chanId);
1280
1281 if (proglist.empty() ||
1282 proglist.size() != ch_proglist.size())
1283 continue;
1284
1285 bool isAlt = true;
1286 for (size_t j = 0; j < proglist.size(); ++j)
1287 {
1288 isAlt &= proglist[j]->IsSameTitleTimeslotAndChannel(*ch_proglist[j]);
1289 }
1290
1291 if (isAlt)
1292 {
1293 si = i;
1294 break;
1295 }
1296 }
1297
1299
1300 return si;
1301}
1302
1303
1304static constexpr uint64_t MKKEY(uint64_t IDX, uint64_t SEL)
1305 { return (IDX << 32) | SEL; }
1306
1308{
1309 ChannelInfoList selected;
1310
1311 int idx = GetStartChannelOffset();
1312 if (idx < 0)
1313 return selected;
1314
1315 uint si = m_channelInfoIdx[idx];
1316
1317 std::vector<uint64_t> sel;
1318 sel.push_back( MKKEY(idx, si) );
1319
1320 const ChannelInfo *ch = GetChannelInfo(sel[0]>>32, sel[0]&0xffff);
1321 if (!ch)
1322 return selected;
1323
1324 selected.push_back(*ch);
1325 if (m_channelInfos[idx].size() <= 1)
1326 return selected;
1327
1328 ProgramList proglist = GetProgramList(selected[0].m_chanId);
1329
1330 if (proglist.empty())
1331 return selected;
1332
1333 for (size_t i = 0; i < m_channelInfos[idx].size(); ++i)
1334 {
1335 const ChannelInfo *ci = GetChannelInfo(idx, i);
1336 if (ci && (i != si) &&
1337 (ci->m_callSign == ch->m_callSign) && (ci->m_chanNum == ch->m_chanNum))
1338 {
1339 sel.push_back( MKKEY(idx, i) );
1340 }
1341 }
1342
1343 for (size_t i = 0; i < m_channelInfos[idx].size(); ++i)
1344 {
1345 const ChannelInfo *ci = GetChannelInfo(idx, i);
1346 if (ci && (i != si) &&
1347 (ci->m_callSign == ch->m_callSign) && (ci->m_chanNum != ch->m_chanNum))
1348 {
1349 sel.push_back( MKKEY(idx, i) );
1350 }
1351 }
1352
1353 for (size_t i = 0; i < m_channelInfos[idx].size(); ++i)
1354 {
1355 const ChannelInfo *ci = GetChannelInfo(idx, i);
1356 if ((i != si) && (ci->m_callSign != ch->m_callSign))
1357 {
1358 sel.push_back( MKKEY(idx, i) );
1359 }
1360 }
1361
1362 for (size_t i = 1; i < sel.size(); ++i)
1363 {
1364 const ChannelInfo *ci = GetChannelInfo(sel[i]>>32, sel[i]&0xffff);
1365 const ProgramList ch_proglist = GetProgramList(ch->m_chanId);
1366
1367 if (!ci || proglist.size() != ch_proglist.size())
1368 continue;
1369
1370 bool isAlt = true;
1371 for (size_t j = 0; j < proglist.size(); ++j)
1372 {
1373 isAlt &= proglist[j]->IsSameTitleTimeslotAndChannel(*ch_proglist[j]);
1374 }
1375
1376 if (isAlt)
1377 selected.push_back(*ci);
1378 }
1379
1380 return selected;
1381}
1382#undef MKKEY
1383
1385{
1386 m_updateTimer->stop();
1388 m_updateTimer->start(kUpdateMS);
1389}
1390
1391void GuideGrid::fillChannelInfos(bool gotostartchannel)
1392{
1393 m_channelInfos.clear();
1394 m_channelInfoIdx.clear();
1396
1397 uint avail = 0;
1398 const ChannelUtil::OrderBy ordering = m_channelOrdering == "channum" ?
1400 ChannelInfoList channels = ChannelUtil::LoadChannels(0, 0, avail, true,
1401 ordering,
1403 0,
1404 (m_changrpid < 0) ? 0 : m_changrpid);
1405
1406 using uint_list_t = std::vector<unsigned int>;
1407 QMap<QString,uint_list_t> channum_to_index_map;
1408 QMap<QString,uint_list_t> callsign_to_index_map;
1409
1410 for (size_t i = 0; i < channels.size(); ++i)
1411 {
1412 uint chan = i;
1413 if (m_sortReverse)
1414 {
1415 chan = channels.size() - i - 1;
1416 }
1417
1418 bool ndup = !channum_to_index_map[channels[chan].m_chanNum].empty();
1419 bool cdup = !callsign_to_index_map[channels[chan].m_callSign].empty();
1420
1421 if (ndup && cdup)
1422 continue;
1423
1424 const ChannelInfo& val(channels[chan]);
1425
1426 channum_to_index_map[val.m_chanNum].push_back(GetChannelCount());
1427 callsign_to_index_map[val.m_callSign].push_back(GetChannelCount());
1428
1429 // add the new channel to the list
1430 db_chan_list_t tmp;
1431 tmp.push_back(val);
1432 m_channelInfos.push_back(tmp);
1433 }
1434
1435 // handle duplicates
1436 for (auto & channel : channels)
1437 {
1438 const uint_list_t &ndups = channum_to_index_map[channel.m_chanNum];
1439 for (unsigned int ndup : ndups)
1440 {
1441 if (channel.m_chanId != m_channelInfos[ndup][0].m_chanId &&
1442 channel.m_callSign == m_channelInfos[ndup][0].m_callSign)
1443 m_channelInfos[ndup].push_back(channel);
1444 }
1445
1446 const uint_list_t &cdups = callsign_to_index_map[channel.m_callSign];
1447 for (unsigned int cdup : cdups)
1448 {
1449 if (channel.m_chanId != m_channelInfos[cdup][0].m_chanId)
1450 m_channelInfos[cdup].push_back(channel);
1451 }
1452 }
1453
1454 if (gotostartchannel)
1455 {
1456 int ch = FindChannel(m_startChanID, m_startChanNum, false);
1457 m_currentStartChannel = (uint) std::max(0, ch);
1458 }
1459
1460 if (m_channelInfos.empty())
1461 {
1462 LOG(VB_GENERAL, LOG_ERR, "GuideGrid: "
1463 "\n\t\t\tYou don't have any channels defined in the database."
1464 "\n\t\t\tGuide grid will have nothing to show you.");
1465 }
1466}
1467
1468int GuideGrid::FindChannel(uint chanid, const QString &channum,
1469 bool exact) const
1470{
1471 // first check chanid
1472 uint i = chanid ? 0 : GetChannelCount();
1473 for (; i < GetChannelCount(); ++i)
1474 {
1475 if (m_channelInfos[i][0].m_chanId == chanid)
1476 return i;
1477 }
1478
1479 // then check for chanid in duplicates
1480 i = chanid ? 0 : GetChannelCount();
1481 for (; i < GetChannelCount(); ++i)
1482 {
1483 for (size_t j = 1; j < m_channelInfos[i].size(); ++j)
1484 {
1485 if (m_channelInfos[i][j].m_chanId == chanid)
1486 return i;
1487 }
1488 }
1489
1490 // then check channum, first only
1491 i = (channum.isEmpty()) ? GetChannelCount() : 0;
1492 for (; i < GetChannelCount(); ++i)
1493 {
1494 if (m_channelInfos[i][0].m_chanNum == channum)
1495 return i;
1496 }
1497
1498 // then check channum duplicates
1499 i = (channum.isEmpty()) ? GetChannelCount() : 0;
1500 for (; i < GetChannelCount(); ++i)
1501 {
1502 for (size_t j = 1; j < m_channelInfos[i].size(); ++j)
1503 {
1504 if (m_channelInfos[i][j].m_chanNum == channum)
1505 return i;
1506 }
1507 }
1508
1509 if (exact || channum.isEmpty())
1510 return -1;
1511
1512 ChannelInfoList list;
1513 QVector<int> idxList;
1514 for (i = 0; i < GetChannelCount(); ++i)
1515 {
1516 for (size_t j = 0; j < m_channelInfos[i].size(); ++j)
1517 {
1518 list.push_back(m_channelInfos[i][j]);
1519 idxList.push_back(i);
1520 }
1521 }
1522 int result = ChannelUtil::GetNearestChannel(list, channum);
1523 if (result >= 0)
1524 result = idxList[result];
1525 return result;
1526}
1527
1529{
1530 m_timeList->Reset();
1531
1532 QDateTime starttime = m_currentStartTime;
1533
1536
1537 for (int x = 0; x < m_timeCount; ++x)
1538 {
1539 int mins = starttime.time().minute();
1540 mins = 5 * (mins / 5);
1541 if (mins % 30 == 0)
1542 {
1543 QString timeStr = MythDate::toString(starttime, MythDate::kTime);
1544
1545 InfoMap infomap;
1546 infomap["starttime"] = timeStr;
1547
1548 QDateTime endtime = starttime.addSecs(kThirtyMinutes);
1549
1550 infomap["endtime"] = MythDate::toString(endtime, MythDate::kTime);
1551
1552 auto *item = new MythUIButtonListItem(m_timeList, timeStr);
1553
1554 item->SetTextFromMap(infomap);
1555 }
1556
1557 starttime = starttime.addSecs(kFiveMinutes);
1558 }
1559 m_currentEndTime = starttime;
1560}
1561
1562void GuideGrid::fillProgramInfos(bool useExistingData)
1563{
1564 fillProgramRowInfos(-1, useExistingData);
1565}
1566
1568{
1569 auto *proglist = new ProgramList();
1570
1571 if (proglist)
1572 {
1573 MSqlBindings bindings;
1574 QString querystr = "WHERE program.chanid = :CHANID "
1575 " AND program.endtime >= :STARTTS "
1576 " AND program.starttime <= :ENDTS "
1577 " AND program.starttime >= :STARTLIMITTS "
1578 " AND program.manualid = 0 ";
1579 QDateTime starttime = m_currentStartTime.addSecs(0 - m_currentStartTime.time().second());
1580 bindings[":CHANID"] = GetChannelInfo(chanNum)->m_chanId;
1581 bindings[":STARTTS"] = starttime;
1582 bindings[":STARTLIMITTS"] = starttime.addDays(-1);
1583 bindings[":ENDTS"] = m_currentEndTime.addSecs(0 - m_currentEndTime.time().second());
1584
1585 LoadFromProgram(*proglist, querystr, bindings, m_recList,
1587 }
1588
1589 return proglist;
1590}
1591
1592void GuideGrid::fillProgramRowInfos(int firstRow, bool useExistingData)
1593{
1594 bool allRows = false;
1595 unsigned int numRows = 1;
1596 if (firstRow < 0)
1597 {
1598 firstRow = 0;
1599 allRows = true;
1600 numRows = std::min((unsigned int)m_channelInfos.size(),
1601 (unsigned int)m_guideGrid->getChannelCount());
1602 }
1603 QVector<int> chanNums;
1604 QVector<ProgramList*> proglists;
1605
1606 for (unsigned int i = 0; i < numRows; ++i)
1607 {
1608 unsigned int row = i + firstRow;
1609 // never divide by zero..
1611 return;
1612
1613 for (int x = 0; x < m_timeCount; ++x)
1614 {
1615 m_programInfos[row][x] = nullptr;
1616 }
1617
1618 if (m_channelInfos.empty())
1619 return;
1620
1621 int chanNum = row + m_currentStartChannel;
1622 if (chanNum >= (int) m_channelInfos.size())
1623 chanNum -= (int) m_channelInfos.size();
1624 if (chanNum >= (int) m_channelInfos.size())
1625 return;
1626
1627 chanNum = std::max(chanNum, 0);
1628
1629 ProgramList *proglist = nullptr;
1630 if (useExistingData)
1631 proglist = CopyProglist(m_programs[row]);
1632 chanNums.push_back(chanNum);
1633 proglists.push_back(proglist);
1634 }
1635 if (allRows)
1636 {
1637 for (unsigned int i = numRows;
1638 i < (unsigned int) m_guideGrid->getChannelCount(); ++i)
1639 {
1640 delete m_programs[i];
1641 m_programs[i] = nullptr;
1643 }
1644 }
1645
1647
1648 GuideStatus gs(firstRow, chanNums.size(), chanNums,
1653 auto *updater = new GuideUpdateProgramRow(this, gs, proglists);
1654 if (updater)
1655 m_threadPool.start(new GuideHelper(this, updater), "GuideHelper");
1656}
1657
1659 const QDateTime& start,
1660 ProgramList *proglist)
1661{
1662 if (row < 0 || row >= m_channelCount ||
1663 start != m_currentStartTime)
1664 {
1665 delete proglist;
1666 return;
1667 }
1668
1669 QDateTime ts = m_currentStartTime;
1670
1671 QDateTime tnow = MythDate::current();
1672 int progPast = 0;
1673 if (tnow > m_currentEndTime)
1674 {
1675 progPast = 100;
1676 }
1677 else if (tnow < m_currentStartTime)
1678 {
1679 progPast = 0;
1680 }
1681 else
1682 {
1683 int played = m_currentStartTime.secsTo(tnow);
1684 int length = m_currentStartTime.secsTo(m_currentEndTime);
1685 if (length)
1686 progPast = played * 100 / length;
1687 }
1688
1689 m_progPast = progPast;
1690
1691 auto program = proglist->begin();
1692 std::vector<ProgramInfo*> unknownlist;
1693 unknownlist.reserve(m_timeCount);
1694 bool unknown = false;
1695 ProgramInfo *proginfo = nullptr;
1696 for (int x = 0; x < m_timeCount; ++x)
1697 {
1698 if (program != proglist->end() &&
1699 (ts >= (*program)->GetScheduledEndTime()))
1700 {
1701 ++program;
1702 }
1703
1704 if ((program == proglist->end()) ||
1705 (ts < (*program)->GetScheduledStartTime()))
1706 {
1707 if (unknown)
1708 {
1709 if (proginfo)
1710 {
1711 proginfo->m_spread++;
1712 proginfo->SetScheduledEndTime(proginfo->GetScheduledEndTime().addSecs(kFiveMinutes));
1713 }
1714 }
1715 else
1716 {
1717 proginfo = new ProgramInfo(kUnknownTitle,
1718 GuideGrid::tr("Unknown", "Unknown program title"),
1719 ts, ts.addSecs(kFiveMinutes));
1720 unknownlist.push_back(proginfo);
1721 proginfo->m_startCol = x;
1722 proginfo->m_spread = 1;
1723 unknown = true;
1724 }
1725 }
1726 else
1727 {
1728 if (proginfo && proginfo == *program)
1729 {
1730 proginfo->m_spread++;
1731 }
1732 else
1733 {
1734 proginfo = *program;
1735 if (proginfo)
1736 {
1737 proginfo->m_startCol = x;
1738 proginfo->m_spread = 1;
1739 unknown = false;
1740 }
1741 }
1742 }
1743 m_programInfos[row][x] = proginfo;
1744 ts = ts.addSecs(kFiveMinutes);
1745 }
1746
1747 // AutoDeleteDeque doesn't work with std::back_inserter
1748 for (auto & pi : unknownlist)
1749 proglist->push_back(pi); // cppcheck-suppress useStlAlgorithm
1750
1751 MythRect programRect = m_ggProgramRect;
1752
1754 double ydifference = 0.0;
1755 double xdifference = 0.0;
1756
1757 if (m_verticalLayout)
1758 {
1759 ydifference = programRect.width() /
1760 (double) m_ggChannelCount;
1761 xdifference = programRect.height() /
1762 (double) m_timeCount;
1763 }
1764 else
1765 {
1766 ydifference = programRect.height() /
1767 (double) m_ggChannelCount;
1768 xdifference = programRect.width() /
1769 (double) m_timeCount;
1770 }
1771
1772 int arrow = GridTimeNormal;
1773 int cnt = 0;
1774 int8_t spread = 1;
1775 QDateTime lastprog;
1776 QRect tempRect;
1777 bool isCurrent = false;
1778
1779 for (int x = 0; x < m_timeCount; ++x)
1780 {
1781 ProgramInfo *pginfo = m_programInfos[row][x];
1782 if (!pginfo)
1783 continue;
1784
1785 spread = 1;
1786 if (pginfo->GetScheduledStartTime() != lastprog)
1787 {
1788 arrow = GridTimeNormal;
1789 if (pginfo->GetScheduledStartTime() < m_firstTime.addSecs(-300))
1790 arrow |= GridTimeStartsBefore;
1791 if (pginfo->GetScheduledEndTime() > m_lastTime.addSecs(2100))
1792 arrow |= GridTimeEndsAfter;
1793
1794 if (pginfo->m_spread != -1)
1795 {
1796 spread = pginfo->m_spread;
1797 }
1798 else
1799 {
1800 for (int z = x + 1; z < m_timeCount; ++z)
1801 {
1802 ProgramInfo *test = m_programInfos[row][z];
1803 if (test && (test->GetScheduledStartTime() ==
1804 pginfo->GetScheduledStartTime()))
1805 spread++;
1806 }
1807 pginfo->m_spread = spread;
1808 pginfo->m_startCol = x;
1809
1810 for (int z = x + 1; z < x + spread; ++z)
1811 {
1812 ProgramInfo *test = m_programInfos[row][z];
1813 if (test)
1814 {
1815 test->m_spread = spread;
1816 test->m_startCol = x;
1817 }
1818 }
1819 }
1820
1821 if (m_verticalLayout)
1822 {
1823 tempRect = QRect((int)(row * ydifference),
1824 (int)(x * xdifference),
1825 (int)ydifference,
1826 (int)(xdifference * pginfo->m_spread));
1827 }
1828 else
1829 {
1830 tempRect = QRect((int)(x * xdifference),
1831 (int)(row * ydifference),
1832 (int)(xdifference * pginfo->m_spread),
1833 (int)ydifference);
1834 }
1835
1836 // snap to right edge for last entry.
1837 if (tempRect.right() + 2 >= programRect.width())
1838 tempRect.setRight(programRect.width());
1839 if (tempRect.bottom() + 2 >= programRect.bottom())
1840 tempRect.setBottom(programRect.bottom());
1841
1842 isCurrent = m_currentRow == row && (m_currentCol >= x) &&
1843 (m_currentCol < (x + spread));
1844
1845 int recFlag = 0;
1846 switch (pginfo->GetRecordingRuleType())
1847 {
1848 case kSingleRecord:
1849 recFlag = 1;
1850 break;
1851 case kDailyRecord:
1852 recFlag = 2;
1853 break;
1854 case kAllRecord:
1855 recFlag = 4;
1856 break;
1857 case kWeeklyRecord:
1858 recFlag = 5;
1859 break;
1860 case kOneRecord:
1861 recFlag = 6;
1862 break;
1863 case kOverrideRecord:
1864 case kDontRecord:
1865 recFlag = 7;
1866 break;
1867 case kNotRecording:
1868 default:
1869 recFlag = 0;
1870 break;
1871 }
1872
1873 int recStat = 0;
1874 if (pginfo->GetRecordingStatus() == RecStatus::Conflict ||
1876 recStat = 2;
1877 else if (pginfo->GetRecordingStatus() <= RecStatus::WillRecord)
1878 recStat = 1;
1879 else
1880 recStat = 0;
1881
1882 QString title = (pginfo->GetTitle() == kUnknownTitle) ?
1883 GuideGrid::tr("Unknown", "Unknown program title") :
1884 pginfo->GetTitle();
1885 m_result.emplace_back(
1886 row, cnt, tempRect, title,
1887 pginfo->GetCategory(), arrow, recFlag,
1888 recStat, isCurrent);
1889
1890 cnt++;
1891 }
1892
1893 lastprog = pginfo->GetScheduledStartTime();
1894 }
1895}
1896
1897void GuideGrid::customEvent(QEvent *event)
1898{
1899 if (event->type() == MythEvent::kMythEventMessage)
1900 {
1901 auto *me = dynamic_cast<MythEvent *>(event);
1902 if (me == nullptr)
1903 return;
1904
1905 const QString& message = me->Message();
1906
1907 if (message == "SCHEDULE_CHANGE")
1908 {
1909 GuideHelper::Wait(this);
1912 }
1913 }
1914 else if (event->type() == DialogCompletionEvent::kEventType)
1915 {
1916 auto *dce = (DialogCompletionEvent*)event;
1917
1918 QString resultid = dce->GetId();
1919 QString resulttext = dce->GetResultText();
1920 int buttonnum = dce->GetResult();
1921
1922 if (resultid == "deleterule")
1923 {
1924 auto *record = dce->GetData().value<RecordingRule *>();
1925 if (record)
1926 {
1927 if ((buttonnum > 0) && !record->Delete())
1928 LOG(VB_GENERAL, LOG_ERR, "Failed to delete recording rule");
1929 delete record;
1930 }
1931 }
1932 // Test for this here because it can come from
1933 // different menus.
1934 else if (resulttext == tr("Watch This Channel"))
1935 {
1936 ChannelInfoList selection = GetSelection();
1937 if (SelectionIsTunable(selection))
1938 TV::StartTV(nullptr, kStartTVNoFlags, selection);
1939 }
1940 else if (resultid == "guidemenu")
1941 {
1942 if (resulttext == tr("Record This"))
1943 {
1944 QuickRecord();
1945 }
1946 else if (resulttext == tr("Change to Channel"))
1947 {
1948 enter();
1949 }
1950 else if (resulttext == tr("Program Details"))
1951 {
1952 ShowDetails();
1953 }
1954 else if (resulttext == tr("Reverse Channel Order"))
1955 {
1959 }
1960 else if (resulttext == tr("Channel Search"))
1961 {
1963 }
1964 else if (resulttext == tr("Add To Channel Group"))
1965 {
1968 }
1969 else if (resulttext == tr("Remove from Channel Group"))
1970 {
1972 }
1973 else if (resulttext == tr("Choose Channel Group"))
1974 {
1976 }
1977 else if (resulttext == tr("Recording Options"))
1978 {
1980 }
1981 else if (resulttext == tr("Jump to Time"))
1982 {
1984 }
1985 }
1986 else if (resultid == "recmenu")
1987 {
1988 if (resulttext == tr("Edit Recording Status"))
1989 {
1990 EditRecording();
1991 }
1992 else if (resulttext == tr("Edit Schedule"))
1993 {
1994 EditScheduled();
1995 }
1996 else if (resulttext == tr("Show Upcoming"))
1997 {
1998 ShowUpcoming();
1999 }
2000 else if (resulttext == tr("Previously Recorded"))
2001 {
2002 ShowPrevious();
2003 }
2004 else if (resulttext == tr("Custom Edit"))
2005 {
2006 EditCustom();
2007 }
2008 else if (resulttext == tr("Delete Rule"))
2009 {
2010 deleteRule();
2011 }
2012
2013 }
2014 else if (resultid == "channelgrouptogglemenu")
2015 {
2016 int changroupid = ChannelGroup::GetChannelGroupId(resulttext);
2017
2018 if (changroupid > 0)
2019 toggleChannelFavorite(changroupid);
2020 }
2021 else if (resultid == "channelgroupmenu")
2022 {
2023 if (buttonnum >= 0)
2024 {
2025 int changroupid = -1;
2026
2027 if (resulttext == QObject::tr("All Channels"))
2028 changroupid = -1;
2029 else
2030 changroupid = ChannelGroup::GetChannelGroupId(resulttext);
2031
2032 m_changrpid = changroupid;
2035 updateInfo();
2036
2037 QString changrpname;
2039
2040 if (m_changroupname)
2041 m_changroupname->SetText(changrpname);
2042
2043 // Use the selected channel group as default, overriding the default
2044 // channel group from the database, if the guide is not embedded
2045 // in an active player.
2046 if (!m_player)
2047 {
2049 LOG(VB_GENERAL, LOG_INFO, LOC +
2050 QString("Change active channel group to %1 %2")
2051 .arg(m_changrpid).arg(changrpname));
2052 }
2053 }
2054 }
2055 else if (resultid == "jumptotime")
2056 {
2057 QDateTime datetime = dce->GetData().toDateTime();
2058 moveToTime(datetime);
2059 }
2060 else
2061 {
2063 }
2064 }
2065 else if (event->type() == UpdateGuideEvent::kEventType)
2066 {
2067 auto *uge = dynamic_cast<UpdateGuideEvent*>(event);
2068 if (uge && uge->m_updater)
2069 {
2070 uge->m_updater->ExecuteUI();
2071 delete uge->m_updater;
2072 uge->m_updater = nullptr;
2073 }
2074 }
2075}
2076
2078{
2079 if (m_dateText)
2081 if (m_longdateText)
2084}
2085
2086void GuideGrid::updateProgramsUI(unsigned int firstRow, unsigned int numRows,
2087 int progPast,
2088 const QVector<ProgramList*> &proglists,
2089 const ProgInfoGuideArray &programInfos,
2090 const std::list<GuideUIElement> &elements)
2091{
2092 for (unsigned int i = 0; i < numRows; ++i)
2093 {
2094 unsigned int row = i + firstRow;
2095 m_guideGrid->ResetRow(row);
2096 if (m_programs[row] != proglists[i])
2097 {
2098 delete m_programs[row];
2099 m_programs[row] = proglists[i];
2100 }
2101 }
2102 m_guideGrid->SetProgPast(progPast);
2103 for (const auto & r : elements)
2104 {
2105 m_guideGrid->SetProgramInfo(r.m_row, r.m_col, r.m_area, r.m_title,
2106 r.m_category, r.m_arrow, r.m_recType,
2107 r.m_recStat, r.m_selected);
2108 }
2109 for (unsigned int i = firstRow; i < firstRow + numRows; ++i)
2110 {
2111 for (int j = 0; j < MAX_DISPLAY_TIMES; ++j)
2112 m_programInfos[i][j] = programInfos[i][j];
2113 if (i == (unsigned int)m_currentRow)
2114 updateInfo();
2115 }
2117}
2118
2120{
2121 auto *updater = new GuideUpdateChannels(this, m_currentStartChannel);
2122 m_threadPool.start(new GuideHelper(this, updater), "GuideHelper");
2123}
2124
2125void GuideGrid::updateChannelsNonUI(QVector<ChannelInfo *> &chinfos,
2126 QVector<bool> &unavailables)
2127{
2129
2130 for (unsigned int y = 0; (y < (unsigned int)m_channelCount) && chinfo; ++y)
2131 {
2132 unsigned int chanNumber = y + m_currentStartChannel;
2133 if (chanNumber >= m_channelInfos.size())
2134 chanNumber -= m_channelInfos.size();
2135 if (chanNumber >= m_channelInfos.size())
2136 break;
2137
2138 chinfo = GetChannelInfo(chanNumber);
2139
2140 bool unavailable = false;
2141 bool try_alt = false;
2142
2143 if (m_player)
2144 {
2146 const PlayerContext* ctx = m_player->GetPlayerContext();
2147 if (ctx && chinfo)
2148 try_alt = !TV::IsTunable(chinfo->m_chanId);
2150 }
2151
2152 if (try_alt)
2153 {
2154 unavailable = true;
2155
2156 // Try alternates with same channum if applicable
2157 uint alt = GetAlternateChannelIndex(chanNumber, true);
2158 if (alt != m_channelInfoIdx[chanNumber])
2159 {
2160 unavailable = false;
2161 m_channelInfoIdx[chanNumber] = alt;
2162 chinfo = GetChannelInfo(chanNumber);
2163 }
2164
2165 // Try alternates with different channum if applicable
2166 if (unavailable && chinfo &&
2167 !GetProgramList(chinfo->m_chanId).empty())
2168 {
2169 alt = GetAlternateChannelIndex(chanNumber, false);
2170 unavailable = (alt == m_channelInfoIdx[chanNumber]);
2171 }
2172 }
2173 chinfos.push_back(chinfo);
2174 unavailables.push_back(unavailable);
2175 }
2176}
2177
2178void GuideGrid::updateChannelsUI(const QVector<ChannelInfo *> &chinfos,
2179 const QVector<bool> &unavailables)
2180{
2182 for (int i = 0; i < chinfos.size(); ++i)
2183 {
2184 ChannelInfo *chinfo = chinfos[i];
2185 bool unavailable = unavailables[i];
2186 auto *item = new MythUIButtonListItem(m_channelList,
2187 chinfo ? chinfo->GetFormatted(ChannelInfo::kChannelShort) : QString());
2188
2189 QString state = "available";
2190 if (unavailable)
2191 state = (m_changrpid == -1) ? "unavailable" : "favunavailable";
2192 else
2193 state = (m_changrpid == -1) ? "available" : "favourite";
2194
2195 item->SetFontState(state);
2196 item->DisplayState(state, "chanstatus");
2197
2198 if (chinfo)
2199 {
2200 InfoMap infomap;
2201 chinfo->ToMap(infomap);
2202 item->SetTextFromMap(infomap);
2203
2204 if (!chinfo->m_icon.isEmpty())
2205 {
2206 QString iconurl =
2207 gCoreContext->GetMasterHostPrefix("ChannelIcons",
2208 chinfo->m_icon);
2209 item->SetImage(iconurl, "channelicon");
2210 }
2211 }
2212 }
2214}
2215
2217{
2218 if (m_currentRow < 0 || m_currentCol < 0)
2219 return;
2220
2222 if (!pginfo)
2223 return;
2224
2225 InfoMap infoMap;
2226
2227 int chanNum = m_currentRow + m_currentStartChannel;
2228 if (chanNum >= (int)m_channelInfos.size())
2229 chanNum -= (int)m_channelInfos.size();
2230 if (chanNum >= (int)m_channelInfos.size())
2231 return;
2232 chanNum = std::max(chanNum, 0);
2233
2234 ChannelInfo *chinfo = GetChannelInfo(chanNum);
2235
2236 if (m_channelImage)
2237 {
2239 if (!chinfo->m_icon.isEmpty())
2240 {
2241 QString iconurl = gCoreContext->GetMasterHostPrefix("ChannelIcons",
2242 chinfo->m_icon);
2243
2244 m_channelImage->SetFilename(iconurl);
2246 }
2247 }
2248
2249 chinfo->ToMap(infoMap);
2250 pginfo->ToMap(infoMap);
2251 // HACK - This should be done in ProgramInfo, but that needs more careful
2252 // review since it may have unintended consequences so we're doing it here
2253 // for now
2254 if (infoMap["title"] == kUnknownTitle)
2255 {
2256 infoMap["title"] = tr("Unknown", "Unknown program title");
2257 infoMap["titlesubtitle"] = tr("Unknown", "Unknown program title");
2258 }
2259
2260 SetTextFromMap(infoMap);
2261
2262 MythUIStateType *ratingState = dynamic_cast<MythUIStateType*>
2263 (GetChild("ratingstate"));
2264 if (ratingState)
2265 {
2266 QString rating = QString::number(pginfo->GetStars(10));
2267 ratingState->DisplayState(rating);
2268 }
2270}
2271
2273{
2274 int oldchangrpid = m_changrpid;
2275
2277
2278 if (oldchangrpid != m_changrpid)
2280
2282 updateInfo();
2283
2284 QString changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
2285
2286 if (m_changroupname)
2287 m_changroupname->SetText(changrpname);
2288}
2289
2291{
2293 m_currentRow = 0;
2294
2295 int maxchannel = 0;
2297 maxchannel = std::max((int)GetChannelCount() - 1, 0);
2298 m_channelCount = std::min(m_guideGrid->getChannelCount(), maxchannel + 1);
2299
2302}
2303
2304// mode 0 Include empty channel groups
2305// mode 1 Exclude empty channel groups
2306// mode 2 Only Manual channel groups
2308{
2309 ChannelGroupList channels;
2310 if (mode == 2)
2311 channels = ChannelGroup::GetManualChannelGroups(true);
2312 else
2313 channels = ChannelGroup::GetChannelGroups(mode == 0);
2314
2315 if (channels.empty())
2316 {
2317 QString message = tr("You don't have any channel groups defined");
2318
2319 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2320
2321 auto *okPopup = new MythConfirmationDialog(popupStack, message, false);
2322 if (okPopup->Create())
2323 popupStack->AddScreen(okPopup);
2324 else
2325 delete okPopup;
2326
2327 return;
2328 }
2329
2330 QString label = tr("Select Channel Group");
2331
2332 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2333 auto *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
2334
2335 if (menuPopup->Create())
2336 {
2337 if (mode == 0 || mode == 2)
2338 {
2339 // add channel to group menu
2340 menuPopup->SetReturnEvent(this, "channelgrouptogglemenu");
2341 }
2342 else
2343 {
2344 // switch to channel group menu
2345 menuPopup->SetReturnEvent(this, "channelgroupmenu");
2346 menuPopup->AddButton(QObject::tr("All Channels"));
2347 }
2348
2349 for (auto & channel : channels)
2350 {
2351 menuPopup->AddButton(channel.m_name);
2352 }
2353
2354 popupStack->AddScreen(menuPopup);
2355 }
2356 else
2357 {
2358 delete menuPopup;
2359 }
2360}
2361
2363{
2365
2366 if (grpid == -1)
2367 {
2368 if (m_changrpid == -1)
2369 return;
2370 grpid = m_changrpid;
2371 }
2372
2373 // Get current channel id, and make sure it exists...
2374 int chanNum = m_currentRow + m_currentStartChannel;
2375 if (chanNum >= (int)m_channelInfos.size())
2376 chanNum -= (int)m_channelInfos.size();
2377 if (chanNum >= (int)m_channelInfos.size())
2378 return;
2379 chanNum = std::max(chanNum, 0);
2380
2381 ChannelInfo *ch = GetChannelInfo(chanNum);
2382 uint chanid = ch->m_chanId;
2383
2384 // All Channels plus all automatic channel groups
2386 {
2387 // If currently viewing all channels, allow to add only not delete
2388 ChannelGroup::ToggleChannel(chanid, grpid, false);
2389 }
2390 else
2391 {
2392 // Only allow delete if viewing the favorite group in question
2393 ChannelGroup::ToggleChannel(chanid, grpid, true);
2394 }
2395
2396 // Regenerate the list of non empty groups in case it did change
2398
2399 // If viewing a manual group such as Favorites, refresh because a channel was removed
2401 {
2404 updateInfo();
2405 }
2406}
2407
2409{
2411
2412 if (!test)
2413 {
2415 return;
2416 }
2417
2418 int8_t startCol = test->m_startCol;
2419 m_currentCol = startCol - 1;
2420
2421 if (m_currentCol < 0)
2422 {
2423 m_currentCol = 0;
2425 }
2426 else
2427 {
2429 }
2430}
2431
2433{
2435
2436 if (!test)
2437 {
2439 return;
2440 }
2441
2442 int8_t spread = test->m_spread;
2443 int8_t startCol = test->m_startCol;
2444
2445 m_currentCol = startCol + spread;
2446
2447 if (m_currentCol > m_timeCount - 1)
2448 {
2451 }
2452 else
2453 {
2455 }
2456}
2457
2459{
2460 m_currentRow++;
2461
2462 if (m_currentRow > m_channelCount - 1)
2463 {
2466 }
2467 else
2468 {
2470 }
2471}
2472
2474{
2475 m_currentRow--;
2476
2477 if (m_currentRow < 0)
2478 {
2479 m_currentRow = 0;
2481 }
2482 else
2483 {
2485 }
2486}
2487
2489{
2490 switch (movement)
2491 {
2492 case kScrollLeft :
2494 break;
2495 case kScrollRight :
2497 break;
2498 case kPageLeft :
2500 break;
2501 case kPageRight :
2503 break;
2504 case kDayLeft :
2506 break;
2507 case kDayRight :
2509 break;
2510 default :
2511 break;
2512 }
2513
2514 fillTimeInfos();
2517}
2518
2520{
2521 switch (movement)
2522 {
2523 case kScrollDown :
2525 break;
2526 case kScrollUp :
2528 break;
2529 case kPageDown :
2531 break;
2532 case kPageUp :
2534 break;
2535 default :
2536 break;
2537 }
2538
2541}
2542
2543void GuideGrid::moveToTime(const QDateTime& datetime)
2544{
2545 if (!datetime.isValid())
2546 return;
2547
2548 m_currentStartTime = datetime;
2549
2550 fillTimeInfos();
2553}
2554
2555void GuideGrid::setStartChannel(int newStartChannel)
2556{
2557 if (newStartChannel < 0)
2558 m_currentStartChannel = newStartChannel + GetChannelCount();
2559 else if (newStartChannel >= (int) GetChannelCount())
2560 m_currentStartChannel = newStartChannel - GetChannelCount();
2561 else
2562 m_currentStartChannel = newStartChannel;
2563}
2564
2566{
2567 if (m_allowFinder)
2569}
2570
2572{
2573 if (!m_player)
2574 return;
2575
2576 m_updateTimer->stop();
2577
2578 channelUpdate();
2579
2580 // Don't perform transition effects when guide is being used during playback
2581 GetScreenStack()->PopScreen(this, false);
2582
2583 epgIsVisibleCond.wakeAll();
2584}
2585
2587{
2588 // HACK: Do not allow exit if we have a popup menu open, not convinced
2589 // that this is the right solution
2590 if (GetMythMainWindow()->GetStack("popup stack")->TotalScreens() > 0)
2591 return;
2592
2593 m_updateTimer->stop();
2594
2595 // don't fade the screen if we are returning to the player
2596 if (m_player)
2597 GetScreenStack()->PopScreen(this, false);
2598 else
2599 GetScreenStack()->PopScreen(this, true);
2600
2601 epgIsVisibleCond.wakeAll();
2602}
2603
2605{
2607
2608 if (!pginfo || !pginfo->GetRecordingRuleID())
2609 return;
2610
2611 auto *record = new RecordingRule();
2612 if (!record->LoadByProgram(pginfo))
2613 {
2614 delete record;
2615 return;
2616 }
2617
2618 QString message = tr("Delete '%1' %2 rule?")
2619 .arg(record->m_title, toString(pginfo->GetRecordingRuleType()));
2620
2621 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2622
2623 auto *okPopup = new MythConfirmationDialog(popupStack, message, true);
2624
2625 okPopup->SetReturnEvent(this, "deleterule");
2626 okPopup->SetData(QVariant::fromValue(record));
2627
2628 if (okPopup->Create())
2629 popupStack->AddScreen(okPopup);
2630 else
2631 delete okPopup;
2632}
2633
2635{
2636 if (!m_player)
2637 return;
2638
2640
2641 if (!sel.empty())
2642 {
2644 m_player->ChangeChannel(sel);
2646 }
2647}
2648
2649void GuideGrid::GoTo(int start, int cur_row)
2650{
2651 setStartChannel(start);
2652 m_currentRow = cur_row % m_channelCount;
2656}
2657
2659{
2660 QString txt;
2661 {
2662 QMutexLocker locker(&m_jumpToChannelLock);
2663 if (m_jumpToChannel)
2664 txt = m_jumpToChannel->GetEntry();
2665 }
2666
2667 if (txt.isEmpty())
2668 return;
2669
2670 if (m_jumpToText)
2671 m_jumpToText->SetText(txt);
2672}
2673
2675{
2676 QMutexLocker locker(&m_jumpToChannelLock);
2677 m_jumpToChannel = ptr;
2678
2679 if (!m_jumpToChannel)
2680 {
2681 if (m_jumpToText)
2683
2685 }
2686}
2687
2689{
2690 GetMythMainWindow()->GetPaintWindow()->clearMask();
2691}
2692
2694{
2696 QRegion r1 = QRegion(m_area);
2697 QRegion r2 = QRegion(m_videoRect);
2698 GetMythMainWindow()->GetPaintWindow()->setMask(r1.xored(r2));
2699}
2700
2702{
2703 if (m_player)
2704 HideTVWindow();
2705
2707}
2708
2710{
2711 if (m_player)
2712 EmbedTVWindow();
2713
2715}
2716
2718{
2719 QString message = tr("Jump to a specific date and time in the guide");
2722
2723 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2724 auto *timedlg = new MythTimeInputDialog(popupStack, message, flags);
2725
2726 if (timedlg->Create())
2727 {
2728 timedlg->SetReturnEvent(this, "jumptotime");
2729 popupStack->AddScreen(timedlg);
2730 }
2731 else
2732 {
2733 delete timedlg;
2734 }
2735}
2736
2737#include "moc_guidegrid.cpp"
std::vector< ChannelGroupItem > ChannelGroupList
Definition: channelgroup.h:31
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:130
iterator begin(void)
iterator end(void)
bool empty(void) const
void push_back(T info)
size_t size(void) const
static QString GetStartChannel(uint inputid)
Definition: cardutil.cpp:1803
static bool NotInChannelGroupList(const ChannelGroupList &groupList, int grpid)
static bool InChannelGroupList(const ChannelGroupList &groupList, int grpid)
static QString GetChannelGroupName(int grpid)
static int GetNextChannelGroup(const ChannelGroupList &sorted, int grpid)
static ChannelGroupList GetChannelGroups(bool includeEmpty=true)
static bool ToggleChannel(uint chanid, int changrpid, bool delete_chan)
static ChannelGroupList GetManualChannelGroups(bool includeEmpty=true)
static int GetChannelGroupId(const QString &changroupname)
QString m_chanNum
Definition: channelinfo.h:85
uint m_chanId
Definition: channelinfo.h:84
QString m_icon
Definition: channelinfo.h:92
void ToMap(InfoMap &infoMap)
QString m_callSign
Definition: channelinfo.h:90
QString GetFormatted(ChannelFormat format) const
static int GetNearestChannel(const ChannelInfoList &list, const QString &channum)
@ kChanGroupByChanid
Definition: channelutil.h:218
static ChannelInfoList LoadChannels(uint startIndex, uint count, uint &totalAvailable, bool ignoreHidden=true, OrderBy orderBy=kChanOrderByChanNum, GroupBy groupBy=kChanGroupByChanid, uint sourceID=0, uint channelGroupID=0, bool liveTVOnly=false, const QString &callsign="", const QString &channum="", bool ignoreUntunable=true)
Load channels from database into a list of ChannelInfo objects.
static ChannelInfoList GetChannels(uint sourceid, bool visible_only, const QString &group_by=QString(), uint channel_groupid=0)
Definition: channelutil.h:252
@ kChanOrderByChanNum
Definition: channelutil.h:209
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:40
static const Type kEventType
Definition: mythdialogbox.h:55
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
Definition: guidegrid.cpp:607
void moveToTime(const QDateTime &datetime)
Definition: guidegrid.cpp:2543
bool m_sortReverse
Definition: guidegrid.h:259
void moveUpDown(MoveVector movement)
Definition: guidegrid.cpp:2519
MythUIText * m_jumpToText
Definition: guidegrid.h:292
ChannelGroupList m_changrplist
Definition: guidegrid.h:281
db_chan_list_list_t m_channelInfos
Definition: guidegrid.h:242
QDateTime m_lastTime
Definition: guidegrid.h:266
MythUIText * m_dateText
Definition: guidegrid.h:290
ProgInfoGuideArray m_programInfos
Definition: guidegrid.h:246
void Close() override
Definition: guidegrid.cpp:2586
void PlayerExiting(TV *Player)
Definition: guidegrid.cpp:527
void cursorUp()
Definition: guidegrid.cpp:2473
@ kScrollLeft
Definition: guidegrid.h:191
@ kPageRight
Definition: guidegrid.h:196
@ kScrollRight
Definition: guidegrid.h:192
@ kScrollDown
Definition: guidegrid.h:190
QString m_startChanNum
Definition: guidegrid.h:254
MythUIImage * m_channelImage
Definition: guidegrid.h:294
MythUIButtonList * m_channelList
Definition: guidegrid.h:288
void GoTo(int start, int cur_row) override
Definition: guidegrid.cpp:2649
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
Definition: guidegrid.cpp:583
MythUIButtonList * m_timeList
Definition: guidegrid.h:287
QDateTime m_firstTime
Definition: guidegrid.h:265
ChannelGroupList m_channelGroupListManual
Definition: guidegrid.h:282
QRect m_videoRect
Definition: guidegrid.h:272
bool gestureEvent(MythGestureEvent *event) override
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop.
Definition: guidegrid.cpp:896
ProgramList GetProgramList(uint chanid) const
Definition: guidegrid.cpp:1212
void generateListings()
Definition: guidegrid.cpp:2290
ProgramList * getProgramListFromProgram(int chanNum)
Definition: guidegrid.cpp:1567
ProgramList m_recList
Definition: guidegrid.h:247
void updateChannelsUI(const QVector< ChannelInfo * > &chinfos, const QVector< bool > &unavailables)
Definition: guidegrid.cpp:2178
QRecursiveMutex m_jumpToChannelLock
Definition: guidegrid.h:284
QDateTime GetCurrentStartTime(void) const
Definition: guidegrid.h:131
void ShowMenu(void) override
Definition: guidegrid.cpp:1102
MythUIText * m_changroupname
Definition: guidegrid.h:293
~GuideGrid() override
Definition: guidegrid.cpp:630
void EmbedTVWindow(void)
Definition: guidegrid.cpp:2693
void deleteRule()
Definition: guidegrid.cpp:2604
int GetStartChannelOffset(int row=-1) const
Definition: guidegrid.cpp:1202
void updateChannelsNonUI(QVector< ChannelInfo * > &chinfos, QVector< bool > &unavailables)
Definition: guidegrid.cpp:2125
void updateProgramsUI(unsigned int firstRow, unsigned int numRows, int progPast, const QVector< ProgramList * > &proglists, const ProgInfoGuideArray &programInfos, const std::list< GuideUIElement > &elements)
Definition: guidegrid.cpp:2086
void setStartChannel(int newStartChannel)
Definition: guidegrid.cpp:2555
void cursorRight()
Definition: guidegrid.cpp:2432
QMap< uint, uint > m_channelInfoIdx
Definition: guidegrid.h:243
void SetJumpToChannel(JumpToChannel *ptr) override
Definition: guidegrid.cpp:2674
uint m_startChanID
Definition: guidegrid.h:253
JumpToChannel * m_jumpToChannel
Definition: guidegrid.h:285
uint GetCurrentStartChannel(void) const
Definition: guidegrid.h:130
int m_currentCol
Definition: guidegrid.h:257
uint m_currentStartChannel
Definition: guidegrid.h:252
bool Create(void) override
Definition: guidegrid.cpp:538
std::vector< ProgramList * > m_programs
Definition: guidegrid.h:245
int FindChannel(uint chanid, const QString &channum, bool exact=true) const override
Definition: guidegrid.cpp:1468
void updateJumpToChannel(void)
Definition: guidegrid.cpp:2658
void updateChannels(void)
Definition: guidegrid.cpp:2119
void showProgFinder()
Definition: guidegrid.cpp:2565
GuideGrid(MythScreenStack *parentStack, uint chanid, QString channum, const QDateTime &startTime, TV *player=nullptr, bool embedVideo=false, bool allowFinder=true, int changrpid=-1)
Definition: guidegrid.cpp:485
int m_currentRow
Definition: guidegrid.h:256
QString m_channelOrdering
Definition: guidegrid.h:274
void aboutToShow() override
Definition: guidegrid.cpp:2709
void enter()
Definition: guidegrid.cpp:2571
bool m_embedVideo
Definition: guidegrid.h:269
uint GetChannelCount(void) const
Definition: guidegrid.cpp:1197
void fillChannelInfos(bool gotostartchannel=true)
Definition: guidegrid.cpp:1391
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: guidegrid.cpp:667
bool m_allowFinder
Definition: guidegrid.h:241
ChannelInfo * GetChannelInfo(uint chan_idx, int sel=-1)
Definition: guidegrid.cpp:1179
void updateInfo(void)
Definition: guidegrid.cpp:2216
int m_channelCount
Definition: guidegrid.h:261
void toggleGuideListing()
Definition: guidegrid.cpp:2272
void ToggleMute(bool CycleChannels)
QDateTime m_currentEndTime
Definition: guidegrid.h:251
bool m_verticalLayout
Definition: guidegrid.h:263
void ShowJumpToTime(void)
Definition: guidegrid.cpp:2717
int m_changrpid
Definition: guidegrid.h:280
void ShowRecordingMenu(void)
Definition: guidegrid.cpp:1148
uint GetAlternateChannelIndex(uint chan_idx, bool with_same_channum) const
Definition: guidegrid.cpp:1245
static void HideTVWindow(void)
Definition: guidegrid.cpp:2688
void fillProgramRowInfos(int row, bool useExistingData)
Definition: guidegrid.cpp:1592
void ChannelGroupMenu(int mode=0)
Definition: guidegrid.cpp:2307
void fillProgramInfos(bool useExistingData=false)
Definition: guidegrid.cpp:1562
QTimer * m_updateTimer
Definition: guidegrid.h:276
int m_timeCount
Definition: guidegrid.h:262
void updateDateText(void)
Definition: guidegrid.cpp:2077
TV * m_player
Definition: guidegrid.h:268
ChannelInfoList GetSelection(void) const
Definition: guidegrid.cpp:1307
void customEvent(QEvent *event) override
Definition: guidegrid.cpp:1897
void cursorDown()
Definition: guidegrid.cpp:2458
MThreadPool m_threadPool
Definition: guidegrid.h:278
void cursorLeft()
Definition: guidegrid.cpp:2408
MythUIText * m_longdateText
Definition: guidegrid.h:291
QDateTime m_originalStartTime
Definition: guidegrid.h:249
void channelUpdate()
Definition: guidegrid.cpp:2634
QDateTime m_currentStartTime
Definition: guidegrid.h:250
void toggleChannelFavorite(int grpid=-1)
Definition: guidegrid.cpp:2362
void aboutToHide() override
Definition: guidegrid.cpp:2701
void ChangeVolume(bool Up, int NewVolume=-1)
static void RunProgramGuide(uint startChanId, const QString &startChanNum, const QDateTime &startTime, TV *player=nullptr, bool embedVideo=false, bool allowFinder=true, int changrpid=-1)
Definition: guidegrid.cpp:410
void updateTimeout(void)
Definition: guidegrid.cpp:1384
void fillTimeInfos(void)
Definition: guidegrid.cpp:1528
std::chrono::minutes m_selectRecThreshold
Definition: guidegrid.h:239
void moveLeftRight(MoveVector movement)
Definition: guidegrid.cpp:2488
MythUIGuideGrid * m_guideGrid
Definition: guidegrid.h:289
GuideHelper(GuideGrid *guide, GuideUpdaterBase *updater)
Definition: guidegrid.cpp:356
static QWaitCondition s_wait
Definition: guidegrid.cpp:403
static QMutex s_lock
Definition: guidegrid.cpp:402
static bool IsLoading(GuideGrid *guide)
Definition: guidegrid.cpp:384
static void Wait(GuideGrid *guide)
Definition: guidegrid.cpp:389
void run(void) override
Definition: guidegrid.cpp:362
GuideGrid * m_guide
Definition: guidegrid.cpp:399
GuideUpdaterBase * m_updater
Definition: guidegrid.cpp:400
static QHash< GuideGrid *, uint > s_loading
Definition: guidegrid.cpp:404
const bool m_verticalLayout
Definition: guidegrid.cpp:220
const int m_currentRow
Definition: guidegrid.cpp:218
const int m_channelCount
Definition: guidegrid.cpp:219
const QDateTime m_firstTime
Definition: guidegrid.cpp:221
const uint m_currentStartChannel
Definition: guidegrid.cpp:217
const int m_timeCount
Definition: guidegrid.cpp:219
const QVector< int > m_chanNums
Definition: guidegrid.cpp:213
const MythRect m_ggProgramRect
Definition: guidegrid.cpp:214
const int m_ggChannelCount
Definition: guidegrid.cpp:215
const unsigned int m_firstRow
Definition: guidegrid.cpp:212
GuideStatus(unsigned int firstRow, unsigned int numRows, QVector< int > channums, const MythRect &gg_programRect, int gg_channelCount, QDateTime currentStartTime, QDateTime currentEndTime, uint currentStartChannel, int currentRow, int currentCol, int channelCount, int timeCount, bool verticalLayout, QDateTime firstTime, QDateTime lastTime)
Definition: guidegrid.cpp:192
const QDateTime m_currentStartTime
Definition: guidegrid.cpp:216
const unsigned int m_numRows
Definition: guidegrid.cpp:212
const int m_currentCol
Definition: guidegrid.cpp:218
const QDateTime m_currentEndTime
Definition: guidegrid.cpp:216
const QDateTime m_lastTime
Definition: guidegrid.cpp:221
void ExecuteUI(void) override
Definition: guidegrid.cpp:333
QVector< ChannelInfo * > m_chinfos
Definition: guidegrid.cpp:338
bool ExecuteNonUI(void) override
Definition: guidegrid.cpp:326
QVector< bool > m_unavailables
Definition: guidegrid.cpp:339
GuideUpdateChannels(GuideGrid *guide, uint startChan)
Definition: guidegrid.cpp:324
const QDateTime m_currentStartTime
Definition: guidegrid.cpp:304
const QDateTime m_firstTime
Definition: guidegrid.cpp:312
const MythRect m_ggProgramRect
Definition: guidegrid.cpp:302
GuideUpdateProgramRow(GuideGrid *guide, const GuideStatus &gs, QVector< ProgramList * > proglists)
Definition: guidegrid.cpp:245
const int m_channelCount
Definition: guidegrid.cpp:309
const QDateTime m_currentEndTime
Definition: guidegrid.cpp:305
const int m_ggChannelCount
Definition: guidegrid.cpp:303
bool ExecuteNonUI(void) override
Definition: guidegrid.cpp:265
const QVector< int > m_chanNums
Definition: guidegrid.cpp:301
ProgInfoGuideArray m_programInfos
Definition: guidegrid.cpp:316
const uint m_currentStartChannel
Definition: guidegrid.cpp:306
~GuideUpdateProgramRow() override=default
void ExecuteUI(void) override
Definition: guidegrid.cpp:288
const bool m_verticalLayout
Definition: guidegrid.cpp:311
const unsigned int m_firstRow
Definition: guidegrid.cpp:299
const QDateTime m_lastTime
Definition: guidegrid.cpp:313
const unsigned int m_numRows
Definition: guidegrid.cpp:300
void fillProgramRowInfosWith(int row, const QDateTime &start, ProgramList *proglist)
Definition: guidegrid.cpp:1658
QVector< ProgramList * > m_proglists
Definition: guidegrid.cpp:315
std::list< GuideUIElement > m_result
Definition: guidegrid.cpp:318
virtual ~GuideUpdaterBase()=default
virtual bool ExecuteNonUI(void)=0
GuideUpdaterBase(GuideGrid *guide)
Definition: guidegrid.cpp:227
GuideGrid * m_guide
Definition: guidegrid.cpp:239
virtual void ExecuteUI(void)=0
virtual void SetJumpToChannel(JumpToChannel *ptr)=0
virtual void GoTo(int start, int cur_row)=0
virtual int FindChannel(uint chanid, const QString &channum, bool exact=true) const =0
virtual void deleteLater(void)
Definition: guidegrid.cpp:83
JumpToChannel(JumpToChannelListener *parent, QString start_entry, int start_chan_idx, int cur_chan_idx, uint rows_disp)
Definition: guidegrid.cpp:64
JumpToChannelListener * m_listener
Definition: guidegrid.h:68
int m_previousStartChannelIndex
Definition: guidegrid.h:70
int m_previousCurrentChannelIndex
Definition: guidegrid.h:71
static const uint kJumpToChannelTimeout
Definition: guidegrid.h:75
QString m_entry
Definition: guidegrid.h:69
uint m_rowsDisplayed
Definition: guidegrid.h:72
bool ProcessEntry(const QStringList &actions, const QKeyEvent *e)
Definition: guidegrid.cpp:112
bool Update(void)
Definition: guidegrid.cpp:161
QTimer * m_timer
Definition: guidegrid.h:73
QString GetEntry(void) const
Definition: guidegrid.h:58
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:129
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:552
void setMaxThreadCount(int maxThreadCount)
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Dialog asking for user confirmation.
void SaveSetting(const QString &key, int newValue)
QString GetMasterHostPrefix(const QString &storageGroup=QString(), const QString &path=QString())
int GetNumSetting(const QString &key, int defaultval=0)
bool GetBoolSetting(const QString &key, bool defaultval=false)
Basic menu dialog, message and a list of options.
This class is used as a container for messages.
Definition: mythevent.h:17
const QString & Message() const
Definition: mythevent.h:65
static const Type kMythEventMessage
Definition: mythevent.h:79
A custom event that represents a mouse gesture.
Definition: mythgesture.h:40
Gesture GetGesture() const
Definition: mythgesture.h:85
QWidget * GetPaintWindow()
MythScreenStack * GetMainStack()
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
MythScreenStack * GetStack(const QString &Stackname)
void addListener(QObject *listener)
Add a listener to the observable.
void removeListener(QObject *listener)
Remove a listener to the observable.
Wrapper around QRect allowing us to handle percentage and other relative values for areas in mythui.
Definition: mythrect.h:18
MythPoint topLeft(void) const
Definition: mythrect.cpp:288
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
bool gestureEvent(MythGestureEvent *event) override
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop.
void LoadInBackground(const QString &message="")
virtual void aboutToShow(void)
virtual void aboutToHide(void)
void BuildFocusList(void)
MythScreenStack * GetScreenStack() const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
void SetItemCurrent(MythUIButtonListItem *item)
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
virtual void SetTextFromMap(const InfoMap &infoMap)
int getChannelCount(void) const
bool isVerticalLayout(void) const
void SetProgramInfo(int row, int col, QRect area, const QString &title, const QString &genre, int arrow, int recType, int recStat, bool selected)
void SetProgPast(int ppast)
void ResetRow(int row)
int getTimeCount(void) const
Image widget, displays a single image or multiple images in sequence.
Definition: mythuiimage.h:99
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
void Reset(void) override
Reset the image back to the default defined in the theme.
This widget is used for grouping other widgets for display when a particular named state is called.
bool DisplayState(const QString &name)
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:65
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
The base class on which all widgets and screens are based.
Definition: mythuitype.h:97
MythUIType * GetChildAt(QPoint p, bool recursive=true, bool focusable=true) const
Return the first MythUIType at the given coordinates.
Definition: mythuitype.cpp:227
void SetRedraw(void)
Definition: mythuitype.cpp:299
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
MythUIType * m_parent
Definition: mythuitype.h:308
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:130
MythRect m_area
Definition: mythuitype.h:288
Holds information on recordings and videos.
Definition: programinfo.h:75
float GetStars(void) const
Definition: programinfo.h:454
uint GetRecordingRuleID(void) const
Definition: programinfo.h:461
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:406
void SetScheduledEndTime(const QDateTime &dt)
Definition: programinfo.h:537
QString GetTitle(void) const
Definition: programinfo.h:369
int8_t m_spread
Definition: programinfo.h:858
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:399
int8_t m_startCol
Definition: programinfo.h:859
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10, uint date_format=0) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:459
QString GetCategory(void) const
Definition: programinfo.h:378
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:463
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:31
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
virtual void EditScheduled(void)
Creates a dialog for editing the recording schedule.
virtual void EditRecording(bool may_watch_now=false)
Creates a dialog for editing the recording status, blocking until user leaves dialog.
virtual void ShowDetails(void) const
Show the Program Details screen.
void customEvent(QEvent *event) override
virtual void EditCustom(void)
Creates a dialog for creating a custom recording rule.
virtual void QuickRecord(void)
Create a kSingleRecord or bring up recording dialog.
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
virtual void ShowChannelSearch(void) const
Show the channel search.
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
void ChangeMuteState(bool CycleChannels=false)
void RequestEmbedding(bool Embed, const QRect &Rect={}, const QStringList &Data={})
Control TV playback.
Definition: tv_play.h:158
void VolumeChange(bool Up, int NewVolume=-1)
Definition: tv_play.cpp:7034
static void SetActiveChannelGroupId(int channelgroupid)
Definition: tv_play.h:523
PlayerContext * GetPlayerContext()
Return a pointer to TV::m_playerContext.
Definition: tv_play.cpp:196
void GetPlayerReadLock() const
Definition: tv_play.cpp:10591
void PlaybackExiting(TV *Player)
static bool StartTV(ProgramInfo *TVRec, uint Flags, const ChannelInfoList &Selection=ChannelInfoList())
Start playback of media.
Definition: tv_play.cpp:290
static bool IsTunable(uint ChanId)
Definition: tv_play.cpp:6778
void ReturnPlayerLock() const
Definition: tv_play.cpp:10596
TVState GetState() const
Definition: tv_play.cpp:1373
void UpdateChannelList(int GroupID)
update the channel list with channels from the selected channel group
Definition: tv_play.cpp:1350
void ChangeChannel(const ChannelInfoList &Options)
Definition: tv_play.cpp:6251
GuideUpdaterBase * m_updater
Definition: guidegrid.cpp:347
static const Type kEventType
Definition: guidegrid.cpp:348
UpdateGuideEvent(GuideUpdaterBase *updater)
Definition: guidegrid.cpp:345
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
unsigned int uint
Definition: compat.h:60
#define LOC
Definition: guidegrid.cpp:50
static ProgramList * CopyProglist(ProgramList *proglist)
Definition: guidegrid.cpp:1234
static constexpr int64_t kFiveMinutes
Definition: guidegrid.cpp:58
static constexpr int64_t kEightHours
Definition: guidegrid.cpp:60
static constexpr int64_t kThirtyMinutes
Definition: guidegrid.cpp:59
static constexpr uint64_t MKKEY(uint64_t IDX, uint64_t SEL)
Definition: guidegrid.cpp:1304
static bool SelectionIsTunable(const ChannelInfoList &selection)
Definition: guidegrid.cpp:1096
const QString kUnknownTitle
Definition: guidegrid.cpp:54
QWaitCondition epgIsVisibleCond
Definition: guidegrid.cpp:48
static bool has_action(const QString &action, const QStringList &actions)
Definition: guidegrid.cpp:101
static constexpr int64_t kFourMinutes
Definition: guidegrid.cpp:57
static constexpr int64_t kOneDay
Definition: guidegrid.cpp:61
static constexpr std::chrono::milliseconds kUpdateMS
Definition: guidegrid.cpp:56
std::array< std::array< ProgramInfo *, MAX_DISPLAY_TIMES >, MAX_DISPLAY_CHANS > ProgInfoGuideArray
Definition: guidegrid.h:34
std::vector< ChannelInfo > db_chan_list_t
Definition: guidegrid.h:32
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:101
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
A C++ ripoff of the stroke library for MythTV.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
static constexpr const char * ACTION_LEFT
Definition: mythuiactions.h:18
static constexpr const char * ACTION_DOWN
Definition: mythuiactions.h:17
static constexpr const char * ACTION_RIGHT
Definition: mythuiactions.h:19
static constexpr const char * ACTION_SELECT
Definition: mythuiactions.h:15
static constexpr const char * ACTION_UP
Definition: mythuiactions.h:16
static constexpr int MAX_DISPLAY_TIMES
static constexpr uint8_t GridTimeNormal
static constexpr int MAX_DISPLAY_CHANS
static constexpr uint8_t GridTimeEndsAfter
static constexpr uint8_t GridTimeStartsBefore
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:27
@ kDateFull
Default local time.
Definition: mythdate.h:20
@ kTime
Default local time.
Definition: mythdate.h:23
@ kDateShort
Default local time.
Definition: mythdate.h:21
std::chrono::seconds secsInFuture(const QDateTime &future)
Definition: mythdate.cpp:217
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
def rating(profile, smoonURL, gate)
Definition: scan.py:36
void RunProgramFinder(TV *player, bool embedVideo, bool allowEPG)
Definition: progfind.cpp:32
bool LoadFromProgram(ProgramList &destination, const QString &where, const QString &groupBy, const QString &orderBy, const MSqlBindings &bindings, const ProgramList &schedList)
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, const QString &altTable="", int recordid=-1)
Definition: programinfo.h:947
AutoDeleteDeque< ProgramInfo * > ProgramList
Definition: programinfo.h:38
@ kOneRecord
@ kWeeklyRecord
@ kNotRecording
@ kAllRecord
@ kOverrideRecord
@ kSingleRecord
@ kDailyRecord
@ kDontRecord
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:66
#define ACTION_TOGGLEPGORDER
Definition: tv_actions.h:13
#define ACTION_FINDER
Definition: tv_actions.h:27
#define ACTION_PAGERIGHT
Definition: tv_actions.h:12
#define ACTION_CHANNELSEARCH
Definition: tv_actions.h:28
#define ACTION_TOGGLERECORD
Definition: tv_actions.h:19
#define ACTION_TOGGLEFAV
Definition: tv_actions.h:20
#define ACTION_DAYLEFT
Definition: tv_actions.h:9
#define ACTION_PAGELEFT
Definition: tv_actions.h:11
#define ACTION_MUTEAUDIO
Definition: tv_actions.h:106
#define ACTION_DAYRIGHT
Definition: tv_actions.h:10
#define ACTION_VOLUMEDOWN
Definition: tv_actions.h:111
#define ACTION_GUIDE
Definition: tv_actions.h:26
#define ACTION_VOLUMEUP
Definition: tv_actions.h:110
@ kStartTVNoFlags
Definition: tv_play.h:116
std::vector< uint > RemoteRequestFreeInputList(uint excluded_input)
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:86
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:80