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 for (uint i = 0; i < MAX_DISPLAY_CHANS; i++)
507 m_programs.push_back(nullptr);
508
510 if (startTime.isValid() &&
511 startTime > m_originalStartTime.addSecs(-kEightHours))
512 m_originalStartTime = startTime;
513
514 int secsoffset = -(((m_originalStartTime.time().minute() % 30) * 60) +
515 m_originalStartTime.time().second());
516 m_currentStartTime = m_originalStartTime.addSecs(secsoffset);
518
519 if (m_player)
520 {
521 m_player->IncrRef();
525 }
526}
527
529{
530 if (Player && (Player == m_player))
531 {
532 emit m_player->RequestEmbedding(false);
533 HideTVWindow();
534 m_player->DecrRef();
535 m_player = nullptr;
536 }
537}
538
540{
541 QString windowName = "programguide";
542
543 if (m_embedVideo)
544 windowName = "programguide-video";
545
546 if (!LoadWindowFromXML("schedule-ui.xml", windowName, this))
547 return false;
548
549 bool err = false;
550 UIUtilE::Assign(this, m_timeList, "timelist", &err);
551 UIUtilE::Assign(this, m_channelList, "channellist", &err);
552 UIUtilE::Assign(this, m_guideGrid, "guidegrid", &err);
553 UIUtilW::Assign(this, m_dateText, "datetext");
554 UIUtilW::Assign(this, m_longdateText, "longdatetext");
555 UIUtilW::Assign(this, m_changroupname, "channelgroup");
556 UIUtilW::Assign(this, m_channelImage, "channelicon");
557 UIUtilW::Assign(this, m_jumpToText, "jumptotext");
558
559 if (err)
560 {
561 LOG(VB_GENERAL, LOG_ERR,
562 QString("Cannot load screen '%1'").arg(windowName));
563 return false;
564 }
565
567
568 MythUIImage *videoImage = dynamic_cast<MythUIImage *>(GetChild("video"));
569 if (videoImage && m_embedVideo)
570 m_videoRect = videoImage->GetArea();
571 else
572 m_videoRect = QRect(0,0,0,0);
573
577
579
581 return true;
582}
583
585{
588
590 int maxchannel = GetChannelCount();
591 m_channelCount = std::min(m_channelCount, maxchannel);
592
593 for (int y = 0; y < m_channelCount; ++y)
594 {
595 int chanNum = y + m_currentStartChannel;
596 if (chanNum >= (int) m_channelInfos.size())
597 chanNum -= (int) m_channelInfos.size();
598 if (chanNum >= (int) m_channelInfos.size())
599 continue;
600
601 chanNum = std::max(chanNum, 0);
602
603 delete m_programs[y];
605 }
606}
607
609{
611 m_currentCol = 0;
612
614
616
617 fillProgramInfos(true);
618
619 m_updateTimer->start(kUpdateMS);
620
622
623 QString changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
624
625 if (m_changroupname)
626 m_changroupname->SetText(changrpname);
627
629}
630
632{
633 m_updateTimer->disconnect(this);
634 m_updateTimer = nullptr;
635
636 GuideHelper::Wait(this);
637
639
640 while (!m_programs.empty())
641 {
642 if (m_programs.back())
643 delete m_programs.back();
644 m_programs.pop_back();
645 }
646
647 m_channelInfos.clear();
648
649 gCoreContext->SaveSetting("EPGSortReverse", m_sortReverse ? "1" : "0");
650
651 if (m_player)
652 {
653 // if we have a player and we are returning to it we need
654 // to tell it to stop embedding and return to fullscreen
655 if (m_allowFinder)
656 emit m_player->RequestEmbedding(false);
657
658 // maybe the user selected a different channel group,
659 // tell the player to update its channel list just in case
661 m_player->DecrRef();
662 }
663
664 if (gCoreContext->GetBoolSetting("ChannelGroupRememberLast", false))
665 gCoreContext->SaveSetting("ChannelGroupDefault", m_changrpid);
666}
667
668bool GuideGrid::keyPressEvent(QKeyEvent *event)
669{
670 QStringList actions;
671 bool handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", event, actions);
672
673 if (handled)
674 return true;
675
676 if (!actions.empty())
677 {
678 QMutexLocker locker(&m_jumpToChannelLock);
679
680 if (!m_jumpToChannel)
681 {
682 const QString& chanNum = actions[0];
683 bool isNum = false;
684 (void)chanNum.toInt(&isNum);
685 if (isNum)
686 {
687 // see if we can find a matching channel before creating the JumpToChannel otherwise
688 // JumpToChannel will delete itself in the ctor leading to a segfault
689 int i = FindChannel(0, chanNum, false);
690 if (i >= 0)
691 {
692 m_jumpToChannel = new JumpToChannel(this, chanNum,
696 }
697
698 handled = true;
699 }
700 }
701
702 if (m_jumpToChannel && !handled)
703 handled = m_jumpToChannel->ProcessEntry(actions, event);
704 }
705
706 for (int i = 0; i < actions.size() && !handled; ++i)
707 {
708 const QString& action = actions[i];
709 handled = true;
710 if (action == ACTION_UP)
711 {
713 cursorLeft();
714 else
715 cursorUp();
716 }
717 else if (action == ACTION_DOWN)
718 {
720 cursorRight();
721 else
722 cursorDown();
723 }
724 else if (action == ACTION_LEFT)
725 {
727 cursorUp();
728 else
729 cursorLeft();
730 }
731 else if (action == ACTION_RIGHT)
732 {
734 cursorDown();
735 else
736 cursorRight();
737 }
738 else if (action == "PAGEUP")
739 {
742 else
744 }
745 else if (action == "PAGEDOWN")
746 {
749 else
751 }
752 else if (action == ACTION_PAGELEFT)
753 {
756 else
758 }
759 else if (action == ACTION_PAGERIGHT)
760 {
763 else
765 }
766 else if (action == ACTION_DAYLEFT)
767 {
769 }
770 else if (action == ACTION_DAYRIGHT)
771 {
773 }
774 else if (action == "NEXTFAV")
775 {
777 }
778 else if (action == ACTION_FINDER)
779 {
781 }
782 else if (action == ACTION_CHANNELSEARCH)
783 {
785 }
786 else if (action == "MENU")
787 {
788 ShowMenu();
789 }
790 else if (action == "ESCAPE" || action == ACTION_GUIDE)
791 {
792 Close();
793 }
794 else if (action == ACTION_SELECT)
795 {
796 ProgramInfo *pginfo =
798 auto secsTillStart = pginfo
801 {
802 // See if this show is far enough into the future that it's
803 // probable that the user wanted to schedule it to record
804 // instead of changing the channel.
805 if (pginfo && (pginfo->GetTitle() != kUnknownTitle) &&
806 (secsTillStart >= m_selectRecThreshold))
807 {
809 }
810 else
811 {
812 enter();
813 }
814 }
815 else
816 {
817 // Edit Recording should include "Watch this channel"
818 // is we selected a show that is current.
821 && (secsTillStart < m_selectRecThreshold));
822 }
823 }
824 else if (action == "EDIT")
825 {
827 }
828 else if (action == "CUSTOMEDIT")
829 {
830 EditCustom();
831 }
832 else if (action == "DELETE")
833 {
834 deleteRule();
835 }
836 else if (action == "UPCOMING")
837 {
838 ShowUpcoming();
839 }
840 else if (action == "PREVRECORDED")
841 {
842 ShowPrevious();
843 }
844 else if (action == "DETAILS" || action == "INFO")
845 {
846 ShowDetails();
847 }
848 else if (action == ACTION_TOGGLERECORD)
849 {
850 QuickRecord();
851 }
852 else if (action == ACTION_TOGGLEFAV)
853 {
854 if (m_changrpid == -1)
856 else
858 }
859 else if (action == "CHANUPDATE")
860 {
862 }
863 else if (action == ACTION_VOLUMEUP)
864 {
865 emit ChangeVolume(true);
866 }
867 else if (action == ACTION_VOLUMEDOWN)
868 {
869 emit ChangeVolume(false);
870 }
871 else if (action == "CYCLEAUDIOCHAN")
872 {
873 emit ToggleMute(true);
874 }
875 else if (action == ACTION_MUTEAUDIO)
876 {
877 emit ToggleMute(false);
878 }
879 else if (action == ACTION_TOGGLEPGORDER)
880 {
884 }
885 else
886 {
887 handled = false;
888 }
889 }
890
891 if (!handled && MythScreenType::keyPressEvent(event))
892 handled = true;
893
894 return handled;
895}
896
898{
899 bool handled = true;
900
901 if (!event)
902 {
903 LOG(VB_GENERAL, LOG_INFO, LOC + "Guide Gesture no event");
904 return false;
905 }
906
907 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture event %1")
908 .arg(QString::number(event->GetGesture())));
909 switch (event->GetGesture())
910 {
912 {
913 handled = false;
914
915 // We want the relative position of the click
916 QPoint position = event->GetPosition();
917 if (m_parent)
918 position -= m_parent->GetArea().topLeft();
919
920 MythUIType *type = GetChildAt(position, false, false);
921
922 if (!type)
923 return false;
924
925 auto *object = dynamic_cast<MythUIStateType *>(type);
926
927 if (object)
928 {
929 QString name = object->objectName();
930 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click name %1").arg(name));
931
932 if (name.startsWith("channellist"))
933 {
934 auto* channelList = qobject_cast<MythUIButtonList*>(object);
935
936 if (channelList)
937 {
938 handled = channelList->gestureEvent(event);
939 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click channel list %1").arg(handled));
940 }
941 }
942 else if (name.startsWith("guidegrid"))
943 {
944 auto* guidegrid = qobject_cast<MythUIGuideGrid*>(object);
945
946 if (guidegrid)
947 {
948 handled = true;
949
950 QPoint rowCol = guidegrid->GetRowAndColumn(position - guidegrid->GetArea().topLeft());
951
952 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg %1,%2 (%3,%4)")
953 .arg(rowCol.y())
954 .arg(rowCol.x())
955 .arg(m_currentRow)
956 .arg(m_currentCol)
957 );
958 if ((rowCol.y() >= 0) && (rowCol.x() >= 0))
959 {
960 if ((rowCol.y() == m_currentRow) && (rowCol.x() == m_currentCol))
961 {
963 {
964 // See if this show is far enough into the future that it's
965 // probable that the user wanted to schedule it to record
966 // instead of changing the channel.
967 ProgramInfo *pginfo =
969 auto secsTillStart = pginfo
971 if (pginfo && (pginfo->GetTitle() != kUnknownTitle) &&
972 (secsTillStart >= m_selectRecThreshold))
973 {
974 //EditRecording();
975 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg EditRec"));
976 }
977 else
978 {
979 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg enter"));
980 enter();
981 }
982 }
983 else
984 {
985 //EditRecording();
986 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Guide Gesture Click gg not live"));
987 }
988 }
989 else
990 {
991 bool rowChanged = (rowCol.y() != m_currentRow);
992 bool colChanged = (rowCol.x() != m_currentCol);
993 if (rowChanged)
995
996 m_currentRow = rowCol.y();
997 m_currentCol = rowCol.x();
998
1000 if (colChanged)
1001 {
1002 m_currentStartTime = m_programInfos[m_currentRow][m_currentCol]->GetScheduledStartTime();
1003 fillTimeInfos();
1004 }
1005 if (rowChanged)
1007 if (colChanged)
1009 }
1010 }
1011 }
1012 }
1013
1014 }
1015 }
1016 break;
1017
1019 if (m_verticalLayout)
1020 cursorLeft();
1021 else
1022 cursorUp();
1023 break;
1024
1026 if (m_verticalLayout)
1027 cursorRight();
1028 else
1029 cursorDown();
1030 break;
1031
1033 if (m_verticalLayout)
1034 cursorUp();
1035 else
1036 cursorLeft();
1037 break;
1038
1040 if (m_verticalLayout)
1041 cursorDown();
1042 else
1043 cursorRight();
1044 break;
1045
1047 if (m_verticalLayout)
1049 else
1051 break;
1052
1054 if (m_verticalLayout)
1056 else
1058 break;
1059
1061 if (m_verticalLayout)
1063 else
1065 break;
1066
1068 if (m_verticalLayout)
1070 else
1072 break;
1073
1076 break;
1077
1080 break;
1081
1083 enter();
1084 break;
1085
1086 default:
1087 handled = false;
1088 break;
1089 }
1090
1091 if (!handled && MythScreenType::gestureEvent(event))
1092 handled = true;
1093
1094 return handled;
1095}
1096
1097static bool SelectionIsTunable(const ChannelInfoList &selection)
1098{
1099 return std::ranges::any_of(selection,
1100 [selection](const auto & chan){ return TV::IsTunable(chan.m_chanId); } );
1101}
1102
1104{
1105 QString label = tr("Guide Options");
1106
1107 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1108 auto *menuPopup = new MythDialogBox(label, popupStack, "guideMenuPopup");
1109
1110 if (menuPopup->Create())
1111 {
1112 menuPopup->SetReturnEvent(this, "guidemenu");
1113
1115 menuPopup->AddButton(tr("Change to Channel"));
1117 menuPopup->AddButton(tr("Watch This Channel"));
1118
1119 menuPopup->AddButton(tr("Record This"));
1120
1121 menuPopup->AddButton(tr("Recording Options"), nullptr, true);
1122
1123 menuPopup->AddButton(tr("Program Details"));
1124
1125 menuPopup->AddButton(tr("Jump to Time"), nullptr, true);
1126
1127 menuPopup->AddButton(tr("Reverse Channel Order"));
1128
1129 menuPopup->AddButton(tr("Channel Search"));
1130
1131 if (!m_changrplist.empty())
1132 {
1133 menuPopup->AddButton(tr("Choose Channel Group"));
1134
1136 menuPopup->AddButton(tr("Add To Channel Group"), nullptr, true);
1137 else
1138 menuPopup->AddButton(tr("Remove from Channel Group"));
1139 }
1140
1141 popupStack->AddScreen(menuPopup);
1142 }
1143 else
1144 {
1145 delete menuPopup;
1146 }
1147}
1148
1150{
1151 QString label = tr("Recording Options");
1152
1153 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1154 auto *menuPopup = new MythDialogBox(label, popupStack, "recMenuPopup");
1155
1156 if (menuPopup->Create())
1157 {
1158 menuPopup->SetReturnEvent(this, "recmenu");
1159
1161
1162 if (pginfo && pginfo->GetRecordingRuleID())
1163 menuPopup->AddButton(tr("Edit Recording Status"));
1164 menuPopup->AddButton(tr("Edit Schedule"));
1165 menuPopup->AddButton(tr("Show Upcoming"));
1166 menuPopup->AddButton(tr("Previously Recorded"));
1167 menuPopup->AddButton(tr("Custom Edit"));
1168
1169 if (pginfo && pginfo->GetRecordingRuleID())
1170 menuPopup->AddButton(tr("Delete Rule"));
1171
1172 popupStack->AddScreen(menuPopup);
1173 }
1174 else
1175 {
1176 delete menuPopup;
1177 }
1178}
1179
1181{
1182 sel = (sel >= 0) ? sel : m_channelInfoIdx[chan_idx];
1183
1184 if (chan_idx >= GetChannelCount())
1185 return nullptr;
1186
1187 if (sel >= (int) m_channelInfos[chan_idx].size())
1188 return nullptr;
1189
1190 return &(m_channelInfos[chan_idx][sel]);
1191}
1192
1193const ChannelInfo *GuideGrid::GetChannelInfo(uint chan_idx, int sel) const
1194{
1195 return ((GuideGrid*)this)->GetChannelInfo(chan_idx, sel);
1196}
1197
1199{
1200 return m_channelInfos.size();
1201}
1202
1204{
1205 uint cnt = GetChannelCount();
1206 if (!cnt)
1207 return -1;
1208
1209 row = (row < 0) ? m_currentRow : row;
1210 return (row + m_currentStartChannel) % cnt;
1211}
1212
1214{
1215 ProgramList proglist;
1216 MSqlBindings bindings;
1217 QString querystr =
1218 "WHERE program.chanid = :CHANID AND "
1219 " program.endtime >= :STARTTS AND "
1220 " program.starttime <= :ENDTS AND "
1221 " program.starttime >= :STARTLIMITTS AND "
1222 " program.manualid = 0 ";
1223 QDateTime starttime = m_currentStartTime.addSecs(0 - m_currentStartTime.time().second());
1224 bindings[":STARTTS"] = starttime;
1225 bindings[":STARTLIMITTS"] = starttime.addDays(-1);
1226 bindings[":ENDTS"] = m_currentEndTime.addSecs(0 - m_currentEndTime.time().second());
1227 bindings[":CHANID"] = chanid;
1228
1229 ProgramList dummy;
1230 LoadFromProgram(proglist, querystr, bindings, dummy, ProgGroupBy::ChanNum);
1231
1232 return proglist;
1233}
1234
1236{
1237 if (!proglist)
1238 return nullptr;
1239 auto *result = new ProgramList();
1240 // AutoDeleteDeque doesn't work with std::back_inserter
1241 for (auto & pi : *proglist)
1242 result->push_back(new ProgramInfo(*pi)); // cppcheck-suppress useStlAlgorithm
1243 return result;
1244}
1245
1247 uint chan_idx, bool with_same_channum) const
1248{
1249 uint si = m_channelInfoIdx[chan_idx];
1250 const ChannelInfo *chinfo = GetChannelInfo(chan_idx, si);
1251
1254
1255 const uint cnt = (ctx && chinfo) ? m_channelInfos[chan_idx].size() : 0;
1256 for (uint i = 0; i < cnt; ++i)
1257 {
1258 if (i == si)
1259 continue;
1260
1261 const ChannelInfo *ciinfo = GetChannelInfo(chan_idx, i);
1262 if (!ciinfo)
1263 continue;
1264
1265 bool same_channum = ciinfo->m_chanNum == chinfo->m_chanNum;
1266
1267 if (with_same_channum != same_channum)
1268 continue;
1269
1270 if (!TV::IsTunable(ciinfo->m_chanId))
1271 continue;
1272
1273 if (with_same_channum)
1274 {
1275 si = i;
1276 break;
1277 }
1278
1279 ProgramList proglist = GetProgramList(chinfo->m_chanId);
1280 ProgramList ch_proglist = GetProgramList(ciinfo->m_chanId);
1281
1282 if (proglist.empty() ||
1283 proglist.size() != ch_proglist.size())
1284 continue;
1285
1286 bool isAlt = true;
1287 for (size_t j = 0; j < proglist.size(); ++j)
1288 {
1289 isAlt &= proglist[j]->IsSameTitleTimeslotAndChannel(*ch_proglist[j]);
1290 }
1291
1292 if (isAlt)
1293 {
1294 si = i;
1295 break;
1296 }
1297 }
1298
1300
1301 return si;
1302}
1303
1304
1305static constexpr uint64_t MKKEY(uint64_t IDX, uint64_t SEL)
1306 { return (IDX << 32) | SEL; }
1307
1309{
1310 ChannelInfoList selected;
1311
1312 int idx = GetStartChannelOffset();
1313 if (idx < 0)
1314 return selected;
1315
1316 uint si = m_channelInfoIdx[idx];
1317
1318 std::vector<uint64_t> sel;
1319 sel.push_back( MKKEY(idx, si) );
1320
1321 const ChannelInfo *ch = GetChannelInfo(sel[0]>>32, sel[0]&0xffff);
1322 if (!ch)
1323 return selected;
1324
1325 selected.push_back(*ch);
1326 if (m_channelInfos[idx].size() <= 1)
1327 return selected;
1328
1329 ProgramList proglist = GetProgramList(selected[0].m_chanId);
1330
1331 if (proglist.empty())
1332 return selected;
1333
1334 for (size_t i = 0; i < m_channelInfos[idx].size(); ++i)
1335 {
1336 const ChannelInfo *ci = GetChannelInfo(idx, i);
1337 if (ci && (i != si) &&
1338 (ci->m_callSign == ch->m_callSign) && (ci->m_chanNum == ch->m_chanNum))
1339 {
1340 sel.push_back( MKKEY(idx, i) );
1341 }
1342 }
1343
1344 for (size_t i = 0; i < m_channelInfos[idx].size(); ++i)
1345 {
1346 const ChannelInfo *ci = GetChannelInfo(idx, i);
1347 if (ci && (i != si) &&
1348 (ci->m_callSign == ch->m_callSign) && (ci->m_chanNum != ch->m_chanNum))
1349 {
1350 sel.push_back( MKKEY(idx, i) );
1351 }
1352 }
1353
1354 for (size_t i = 0; i < m_channelInfos[idx].size(); ++i)
1355 {
1356 const ChannelInfo *ci = GetChannelInfo(idx, i);
1357 if ((i != si) && (ci->m_callSign != ch->m_callSign))
1358 {
1359 sel.push_back( MKKEY(idx, i) );
1360 }
1361 }
1362
1363 for (size_t i = 1; i < sel.size(); ++i)
1364 {
1365 const ChannelInfo *ci = GetChannelInfo(sel[i]>>32, sel[i]&0xffff);
1366 const ProgramList ch_proglist = GetProgramList(ch->m_chanId);
1367
1368 if (!ci || proglist.size() != ch_proglist.size())
1369 continue;
1370
1371 bool isAlt = true;
1372 for (size_t j = 0; j < proglist.size(); ++j)
1373 {
1374 isAlt &= proglist[j]->IsSameTitleTimeslotAndChannel(*ch_proglist[j]);
1375 }
1376
1377 if (isAlt)
1378 selected.push_back(*ci);
1379 }
1380
1381 return selected;
1382}
1383#undef MKKEY
1384
1386{
1387 m_updateTimer->stop();
1389 m_updateTimer->start(kUpdateMS);
1390}
1391
1392void GuideGrid::fillChannelInfos(bool gotostartchannel)
1393{
1394 m_channelInfos.clear();
1395 m_channelInfoIdx.clear();
1397
1398 uint avail = 0;
1399 const ChannelUtil::OrderBy ordering = m_channelOrdering == "channum" ?
1401 ChannelInfoList channels = ChannelUtil::LoadChannels(0, 0, avail, true,
1402 ordering,
1404 0,
1405 (m_changrpid < 0) ? 0 : m_changrpid);
1406
1407 using uint_list_t = std::vector<unsigned int>;
1408 QMap<QString,uint_list_t> channum_to_index_map;
1409 QMap<QString,uint_list_t> callsign_to_index_map;
1410
1411 for (size_t i = 0; i < channels.size(); ++i)
1412 {
1413 uint chan = i;
1414 if (m_sortReverse)
1415 {
1416 chan = channels.size() - i - 1;
1417 }
1418
1419 bool ndup = !channum_to_index_map[channels[chan].m_chanNum].empty();
1420 bool cdup = !callsign_to_index_map[channels[chan].m_callSign].empty();
1421
1422 if (ndup && cdup)
1423 continue;
1424
1425 const ChannelInfo& val(channels[chan]);
1426
1427 channum_to_index_map[val.m_chanNum].push_back(GetChannelCount());
1428 callsign_to_index_map[val.m_callSign].push_back(GetChannelCount());
1429
1430 // add the new channel to the list
1431 db_chan_list_t tmp;
1432 tmp.push_back(val);
1433 m_channelInfos.push_back(tmp);
1434 }
1435
1436 // handle duplicates
1437 for (auto & channel : channels)
1438 {
1439 const uint_list_t &ndups = channum_to_index_map[channel.m_chanNum];
1440 for (unsigned int ndup : ndups)
1441 {
1442 if (channel.m_chanId != m_channelInfos[ndup][0].m_chanId &&
1443 channel.m_callSign == m_channelInfos[ndup][0].m_callSign)
1444 m_channelInfos[ndup].push_back(channel);
1445 }
1446
1447 const uint_list_t &cdups = callsign_to_index_map[channel.m_callSign];
1448 for (unsigned int cdup : cdups)
1449 {
1450 if (channel.m_chanId != m_channelInfos[cdup][0].m_chanId)
1451 m_channelInfos[cdup].push_back(channel);
1452 }
1453 }
1454
1455 if (gotostartchannel)
1456 {
1457 int ch = FindChannel(m_startChanID, m_startChanNum, false);
1458 m_currentStartChannel = (uint) std::max(0, ch);
1459 }
1460
1461 if (m_channelInfos.empty())
1462 {
1463 LOG(VB_GENERAL, LOG_ERR, "GuideGrid: "
1464 "\n\t\t\tYou don't have any channels defined in the database."
1465 "\n\t\t\tGuide grid will have nothing to show you.");
1466 }
1467}
1468
1469int GuideGrid::FindChannel(uint chanid, const QString &channum,
1470 bool exact) const
1471{
1472 // first check chanid
1473 uint i = chanid ? 0 : GetChannelCount();
1474 for (; i < GetChannelCount(); ++i)
1475 {
1476 if (m_channelInfos[i][0].m_chanId == chanid)
1477 return i;
1478 }
1479
1480 // then check for chanid in duplicates
1481 i = chanid ? 0 : GetChannelCount();
1482 for (; i < GetChannelCount(); ++i)
1483 {
1484 for (size_t j = 1; j < m_channelInfos[i].size(); ++j)
1485 {
1486 if (m_channelInfos[i][j].m_chanId == chanid)
1487 return i;
1488 }
1489 }
1490
1491 // then check channum, first only
1492 i = (channum.isEmpty()) ? GetChannelCount() : 0;
1493 for (; i < GetChannelCount(); ++i)
1494 {
1495 if (m_channelInfos[i][0].m_chanNum == channum)
1496 return i;
1497 }
1498
1499 // then check channum duplicates
1500 i = (channum.isEmpty()) ? GetChannelCount() : 0;
1501 for (; i < GetChannelCount(); ++i)
1502 {
1503 for (size_t j = 1; j < m_channelInfos[i].size(); ++j)
1504 {
1505 if (m_channelInfos[i][j].m_chanNum == channum)
1506 return i;
1507 }
1508 }
1509
1510 if (exact || channum.isEmpty())
1511 return -1;
1512
1513 ChannelInfoList list;
1514 QVector<int> idxList;
1515 for (i = 0; i < GetChannelCount(); ++i)
1516 {
1517 for (size_t j = 0; j < m_channelInfos[i].size(); ++j)
1518 {
1519 list.push_back(m_channelInfos[i][j]);
1520 idxList.push_back(i);
1521 }
1522 }
1523 int result = ChannelUtil::GetNearestChannel(list, channum);
1524 if (result >= 0)
1525 result = idxList[result];
1526 return result;
1527}
1528
1530{
1531 m_timeList->Reset();
1532
1533 QDateTime starttime = m_currentStartTime;
1534
1537
1538 for (int x = 0; x < m_timeCount; ++x)
1539 {
1540 int mins = starttime.time().minute();
1541 mins = 5 * (mins / 5);
1542 if (mins % 30 == 0)
1543 {
1544 QString timeStr = MythDate::toString(starttime, MythDate::kTime);
1545
1546 InfoMap infomap;
1547 infomap["starttime"] = timeStr;
1548
1549 QDateTime endtime = starttime.addSecs(kThirtyMinutes);
1550
1551 infomap["endtime"] = MythDate::toString(endtime, MythDate::kTime);
1552
1553 auto *item = new MythUIButtonListItem(m_timeList, timeStr);
1554
1555 item->SetTextFromMap(infomap);
1556 }
1557
1558 starttime = starttime.addSecs(kFiveMinutes);
1559 }
1560 m_currentEndTime = starttime;
1561}
1562
1563void GuideGrid::fillProgramInfos(bool useExistingData)
1564{
1565 fillProgramRowInfos(-1, useExistingData);
1566}
1567
1569{
1570 auto *proglist = new ProgramList();
1571
1572 if (proglist)
1573 {
1574 MSqlBindings bindings;
1575 QString querystr = "WHERE program.chanid = :CHANID "
1576 " AND program.endtime >= :STARTTS "
1577 " AND program.starttime <= :ENDTS "
1578 " AND program.starttime >= :STARTLIMITTS "
1579 " AND program.manualid = 0 ";
1580 QDateTime starttime = m_currentStartTime.addSecs(0 - m_currentStartTime.time().second());
1581 bindings[":CHANID"] = GetChannelInfo(chanNum)->m_chanId;
1582 bindings[":STARTTS"] = starttime;
1583 bindings[":STARTLIMITTS"] = starttime.addDays(-1);
1584 bindings[":ENDTS"] = m_currentEndTime.addSecs(0 - m_currentEndTime.time().second());
1585
1586 LoadFromProgram(*proglist, querystr, bindings, m_recList,
1588 }
1589
1590 return proglist;
1591}
1592
1593void GuideGrid::fillProgramRowInfos(int firstRow, bool useExistingData)
1594{
1595 bool allRows = false;
1596 unsigned int numRows = 1;
1597 if (firstRow < 0)
1598 {
1599 firstRow = 0;
1600 allRows = true;
1601 numRows = std::min((unsigned int)m_channelInfos.size(),
1602 (unsigned int)m_guideGrid->getChannelCount());
1603 }
1604 QVector<int> chanNums;
1605 QVector<ProgramList*> proglists;
1606
1607 for (unsigned int i = 0; i < numRows; ++i)
1608 {
1609 unsigned int row = i + firstRow;
1610 // never divide by zero..
1612 return;
1613
1614 for (int x = 0; x < m_timeCount; ++x)
1615 {
1616 m_programInfos[row][x] = nullptr;
1617 }
1618
1619 if (m_channelInfos.empty())
1620 return;
1621
1622 int chanNum = row + m_currentStartChannel;
1623 if (chanNum >= (int) m_channelInfos.size())
1624 chanNum -= (int) m_channelInfos.size();
1625 if (chanNum >= (int) m_channelInfos.size())
1626 return;
1627
1628 chanNum = std::max(chanNum, 0);
1629
1630 ProgramList *proglist = nullptr;
1631 if (useExistingData)
1632 proglist = CopyProglist(m_programs[row]);
1633 chanNums.push_back(chanNum);
1634 proglists.push_back(proglist);
1635 }
1636 if (allRows)
1637 {
1638 for (unsigned int i = numRows;
1639 i < (unsigned int) m_guideGrid->getChannelCount(); ++i)
1640 {
1641 delete m_programs[i];
1642 m_programs[i] = nullptr;
1644 }
1645 }
1646
1648
1649 GuideStatus gs(firstRow, chanNums.size(), chanNums,
1654 auto *updater = new GuideUpdateProgramRow(this, gs, proglists);
1655 if (updater)
1656 m_threadPool.start(new GuideHelper(this, updater), "GuideHelper");
1657}
1658
1660 const QDateTime& start,
1661 ProgramList *proglist)
1662{
1663 if (row < 0 || row >= m_channelCount ||
1664 start != m_currentStartTime)
1665 {
1666 delete proglist;
1667 return;
1668 }
1669
1670 QDateTime ts = m_currentStartTime;
1671
1672 QDateTime tnow = MythDate::current();
1673 int progPast = 0;
1674 if (tnow > m_currentEndTime)
1675 {
1676 progPast = 100;
1677 }
1678 else if (tnow < m_currentStartTime)
1679 {
1680 progPast = 0;
1681 }
1682 else
1683 {
1684 int played = m_currentStartTime.secsTo(tnow);
1685 int length = m_currentStartTime.secsTo(m_currentEndTime);
1686 if (length)
1687 progPast = played * 100 / length;
1688 }
1689
1690 m_progPast = progPast;
1691
1692 auto program = proglist->begin();
1693 std::vector<ProgramInfo*> unknownlist;
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:1802
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:608
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:528
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:584
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:897
ProgramList GetProgramList(uint chanid) const
Definition: guidegrid.cpp:1213
void generateListings()
Definition: guidegrid.cpp:2290
ProgramList * getProgramListFromProgram(int chanNum)
Definition: guidegrid.cpp:1568
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:1103
MythUIText * m_changroupname
Definition: guidegrid.h:293
~GuideGrid() override
Definition: guidegrid.cpp:631
void EmbedTVWindow(void)
Definition: guidegrid.cpp:2693
void deleteRule()
Definition: guidegrid.cpp:2604
int GetStartChannelOffset(int row=-1) const
Definition: guidegrid.cpp:1203
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:539
std::vector< ProgramList * > m_programs
Definition: guidegrid.h:245
int FindChannel(uint chanid, const QString &channum, bool exact=true) const override
Definition: guidegrid.cpp:1469
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:1198
void fillChannelInfos(bool gotostartchannel=true)
Definition: guidegrid.cpp:1392
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: guidegrid.cpp:668
bool m_allowFinder
Definition: guidegrid.h:241
ChannelInfo * GetChannelInfo(uint chan_idx, int sel=-1)
Definition: guidegrid.cpp:1180
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:1149
uint GetAlternateChannelIndex(uint chan_idx, bool with_same_channum) const
Definition: guidegrid.cpp:1246
static void HideTVWindow(void)
Definition: guidegrid.cpp:2688
void fillProgramRowInfos(int row, bool useExistingData)
Definition: guidegrid.cpp:1593
void ChannelGroupMenu(int mode=0)
Definition: guidegrid.cpp:2307
void fillProgramInfos(bool useExistingData=false)
Definition: guidegrid.cpp:1563
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:1308
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:1385
void fillTimeInfos(void)
Definition: guidegrid.cpp:1529
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:1659
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:128
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:98
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:74
float GetStars(void) const
Definition: programinfo.h:453
uint GetRecordingRuleID(void) const
Definition: programinfo.h:460
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:405
void SetScheduledEndTime(const QDateTime &dt)
Definition: programinfo.h:536
QString GetTitle(void) const
Definition: programinfo.h:368
int8_t m_spread
Definition: programinfo.h:857
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:398
int8_t m_startCol
Definition: programinfo.h:858
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:458
QString GetCategory(void) const
Definition: programinfo.h:377
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:462
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:30
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:157
void VolumeChange(bool Up, int NewVolume=-1)
Definition: tv_play.cpp:7028
static void SetActiveChannelGroupId(int channelgroupid)
Definition: tv_play.h:522
PlayerContext * GetPlayerContext()
Return a pointer to TV::m_playerContext.
Definition: tv_play.cpp:196
void GetPlayerReadLock() const
Definition: tv_play.cpp:10545
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:6772
void ReturnPlayerLock() const
Definition: tv_play.cpp:10550
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:6245
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:1235
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:1305
static bool SelectionIsTunable(const ChannelInfoList &selection)
Definition: guidegrid.cpp:1097
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:100
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:26
@ kDateFull
Default local time.
Definition: mythdate.h:19
@ kTime
Default local time.
Definition: mythdate.h:22
@ kDateShort
Default local time.
Definition: mythdate.h:20
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:945
AutoDeleteDeque< ProgramInfo * > ProgramList
Definition: programinfo.h:37
@ 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:115
std::vector< uint > RemoteRequestFreeInputList(uint excluded_input)
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:86
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:80