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::any_of(selection.cbegin(), selection.cend(),
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 progPast = 100;
1676 else if (tnow < m_currentStartTime)
1677 progPast = 0;
1678 else
1679 {
1680 int played = m_currentStartTime.secsTo(tnow);
1681 int length = m_currentStartTime.secsTo(m_currentEndTime);
1682 if (length)
1683 progPast = played * 100 / length;
1684 }
1685
1686 m_progPast = progPast;
1687
1688 auto program = proglist->begin();
1689 std::vector<ProgramInfo*> unknownlist;
1690 bool unknown = false;
1691 ProgramInfo *proginfo = nullptr;
1692 for (int x = 0; x < m_timeCount; ++x)
1693 {
1694 if (program != proglist->end() &&
1695 (ts >= (*program)->GetScheduledEndTime()))
1696 {
1697 ++program;
1698 }
1699
1700 if ((program == proglist->end()) ||
1701 (ts < (*program)->GetScheduledStartTime()))
1702 {
1703 if (unknown)
1704 {
1705 if (proginfo)
1706 {
1707 proginfo->m_spread++;
1708 proginfo->SetScheduledEndTime(proginfo->GetScheduledEndTime().addSecs(kFiveMinutes));
1709 }
1710 }
1711 else
1712 {
1713 proginfo = new ProgramInfo(kUnknownTitle,
1714 GuideGrid::tr("Unknown", "Unknown program title"),
1715 ts, ts.addSecs(kFiveMinutes));
1716 unknownlist.push_back(proginfo);
1717 proginfo->m_startCol = x;
1718 proginfo->m_spread = 1;
1719 unknown = true;
1720 }
1721 }
1722 else
1723 {
1724 if (proginfo && proginfo == *program)
1725 {
1726 proginfo->m_spread++;
1727 }
1728 else
1729 {
1730 proginfo = *program;
1731 if (proginfo)
1732 {
1733 proginfo->m_startCol = x;
1734 proginfo->m_spread = 1;
1735 unknown = false;
1736 }
1737 }
1738 }
1739 m_programInfos[row][x] = proginfo;
1740 ts = ts.addSecs(kFiveMinutes);
1741 }
1742
1743 // AutoDeleteDeque doesn't work with std::back_inserter
1744 for (auto & pi : unknownlist)
1745 proglist->push_back(pi); // cppcheck-suppress useStlAlgorithm
1746
1747 MythRect programRect = m_ggProgramRect;
1748
1750 double ydifference = 0.0;
1751 double xdifference = 0.0;
1752
1753 if (m_verticalLayout)
1754 {
1755 ydifference = programRect.width() /
1756 (double) m_ggChannelCount;
1757 xdifference = programRect.height() /
1758 (double) m_timeCount;
1759 }
1760 else
1761 {
1762 ydifference = programRect.height() /
1763 (double) m_ggChannelCount;
1764 xdifference = programRect.width() /
1765 (double) m_timeCount;
1766 }
1767
1768 int arrow = GridTimeNormal;
1769 int cnt = 0;
1770 int8_t spread = 1;
1771 QDateTime lastprog;
1772 QRect tempRect;
1773 bool isCurrent = false;
1774
1775 for (int x = 0; x < m_timeCount; ++x)
1776 {
1777 ProgramInfo *pginfo = m_programInfos[row][x];
1778 if (!pginfo)
1779 continue;
1780
1781 spread = 1;
1782 if (pginfo->GetScheduledStartTime() != lastprog)
1783 {
1784 arrow = GridTimeNormal;
1785 if (pginfo->GetScheduledStartTime() < m_firstTime.addSecs(-300))
1786 arrow |= GridTimeStartsBefore;
1787 if (pginfo->GetScheduledEndTime() > m_lastTime.addSecs(2100))
1788 arrow |= GridTimeEndsAfter;
1789
1790 if (pginfo->m_spread != -1)
1791 {
1792 spread = pginfo->m_spread;
1793 }
1794 else
1795 {
1796 for (int z = x + 1; z < m_timeCount; ++z)
1797 {
1798 ProgramInfo *test = m_programInfos[row][z];
1799 if (test && (test->GetScheduledStartTime() ==
1800 pginfo->GetScheduledStartTime()))
1801 spread++;
1802 }
1803 pginfo->m_spread = spread;
1804 pginfo->m_startCol = x;
1805
1806 for (int z = x + 1; z < x + spread; ++z)
1807 {
1808 ProgramInfo *test = m_programInfos[row][z];
1809 if (test)
1810 {
1811 test->m_spread = spread;
1812 test->m_startCol = x;
1813 }
1814 }
1815 }
1816
1817 if (m_verticalLayout)
1818 {
1819 tempRect = QRect((int)(row * ydifference),
1820 (int)(x * xdifference),
1821 (int)(ydifference),
1822 (int)(xdifference * pginfo->m_spread));
1823 }
1824 else
1825 {
1826 tempRect = QRect((int)(x * xdifference),
1827 (int)(row * ydifference),
1828 (int)(xdifference * pginfo->m_spread),
1829 (int)ydifference);
1830 }
1831
1832 // snap to right edge for last entry.
1833 if (tempRect.right() + 2 >= programRect.width())
1834 tempRect.setRight(programRect.width());
1835 if (tempRect.bottom() + 2 >= programRect.bottom())
1836 tempRect.setBottom(programRect.bottom());
1837
1838 isCurrent = m_currentRow == row && (m_currentCol >= x) &&
1839 (m_currentCol < (x + spread));
1840
1841 int recFlag = 0;
1842 switch (pginfo->GetRecordingRuleType())
1843 {
1844 case kSingleRecord:
1845 recFlag = 1;
1846 break;
1847 case kDailyRecord:
1848 recFlag = 2;
1849 break;
1850 case kAllRecord:
1851 recFlag = 4;
1852 break;
1853 case kWeeklyRecord:
1854 recFlag = 5;
1855 break;
1856 case kOneRecord:
1857 recFlag = 6;
1858 break;
1859 case kOverrideRecord:
1860 case kDontRecord:
1861 recFlag = 7;
1862 break;
1863 case kNotRecording:
1864 default:
1865 recFlag = 0;
1866 break;
1867 }
1868
1869 int recStat = 0;
1870 if (pginfo->GetRecordingStatus() == RecStatus::Conflict ||
1872 recStat = 2;
1873 else if (pginfo->GetRecordingStatus() <= RecStatus::WillRecord)
1874 recStat = 1;
1875 else
1876 recStat = 0;
1877
1878 QString title = (pginfo->GetTitle() == kUnknownTitle) ?
1879 GuideGrid::tr("Unknown", "Unknown program title") :
1880 pginfo->GetTitle();
1881 m_result.emplace_back(
1882 row, cnt, tempRect, title,
1883 pginfo->GetCategory(), arrow, recFlag,
1884 recStat, isCurrent);
1885
1886 cnt++;
1887 }
1888
1889 lastprog = pginfo->GetScheduledStartTime();
1890 }
1891}
1892
1893void GuideGrid::customEvent(QEvent *event)
1894{
1895 if (event->type() == MythEvent::kMythEventMessage)
1896 {
1897 auto *me = dynamic_cast<MythEvent *>(event);
1898 if (me == nullptr)
1899 return;
1900
1901 const QString& message = me->Message();
1902
1903 if (message == "SCHEDULE_CHANGE")
1904 {
1905 GuideHelper::Wait(this);
1908 }
1909 }
1910 else if (event->type() == DialogCompletionEvent::kEventType)
1911 {
1912 auto *dce = (DialogCompletionEvent*)(event);
1913
1914 QString resultid = dce->GetId();
1915 QString resulttext = dce->GetResultText();
1916 int buttonnum = dce->GetResult();
1917
1918 if (resultid == "deleterule")
1919 {
1920 auto *record = dce->GetData().value<RecordingRule *>();
1921 if (record)
1922 {
1923 if ((buttonnum > 0) && !record->Delete())
1924 LOG(VB_GENERAL, LOG_ERR, "Failed to delete recording rule");
1925 delete record;
1926 }
1927 }
1928 // Test for this here because it can come from
1929 // different menus.
1930 else if (resulttext == tr("Watch This Channel"))
1931 {
1932 ChannelInfoList selection = GetSelection();
1933 if (SelectionIsTunable(selection))
1934 TV::StartTV(nullptr, kStartTVNoFlags, selection);
1935 }
1936 else if (resultid == "guidemenu")
1937 {
1938 if (resulttext == tr("Record This"))
1939 {
1940 QuickRecord();
1941 }
1942 else if (resulttext == tr("Change to Channel"))
1943 {
1944 enter();
1945 }
1946 else if (resulttext == tr("Program Details"))
1947 {
1948 ShowDetails();
1949 }
1950 else if (resulttext == tr("Reverse Channel Order"))
1951 {
1955 }
1956 else if (resulttext == tr("Channel Search"))
1957 {
1959 }
1960 else if (resulttext == tr("Add To Channel Group"))
1961 {
1964 }
1965 else if (resulttext == tr("Remove from Channel Group"))
1966 {
1968 }
1969 else if (resulttext == tr("Choose Channel Group"))
1970 {
1972 }
1973 else if (resulttext == tr("Recording Options"))
1974 {
1976 }
1977 else if (resulttext == tr("Jump to Time"))
1978 {
1980 }
1981 }
1982 else if (resultid == "recmenu")
1983 {
1984 if (resulttext == tr("Edit Recording Status"))
1985 {
1986 EditRecording();
1987 }
1988 else if (resulttext == tr("Edit Schedule"))
1989 {
1990 EditScheduled();
1991 }
1992 else if (resulttext == tr("Show Upcoming"))
1993 {
1994 ShowUpcoming();
1995 }
1996 else if (resulttext == tr("Previously Recorded"))
1997 {
1998 ShowPrevious();
1999 }
2000 else if (resulttext == tr("Custom Edit"))
2001 {
2002 EditCustom();
2003 }
2004 else if (resulttext == tr("Delete Rule"))
2005 {
2006 deleteRule();
2007 }
2008
2009 }
2010 else if (resultid == "channelgrouptogglemenu")
2011 {
2012 int changroupid = ChannelGroup::GetChannelGroupId(resulttext);
2013
2014 if (changroupid > 0)
2015 toggleChannelFavorite(changroupid);
2016 }
2017 else if (resultid == "channelgroupmenu")
2018 {
2019 if (buttonnum >= 0)
2020 {
2021 int changroupid = -1;
2022
2023 if (resulttext == QObject::tr("All Channels"))
2024 changroupid = -1;
2025 else
2026 changroupid = ChannelGroup::GetChannelGroupId(resulttext);
2027
2028 m_changrpid = changroupid;
2031 updateInfo();
2032
2033 QString changrpname;
2035
2036 if (m_changroupname)
2037 m_changroupname->SetText(changrpname);
2038
2039 // Use the selected channel group as default, overriding the default
2040 // channel group from the database, if the guide is not embedded
2041 // in an active player.
2042 if (!m_player)
2043 {
2045 LOG(VB_GENERAL, LOG_INFO, LOC +
2046 QString("Change active channel group to %1 %2")
2047 .arg(m_changrpid).arg(changrpname));
2048 }
2049 }
2050 }
2051 else if (resultid == "jumptotime")
2052 {
2053 QDateTime datetime = dce->GetData().toDateTime();
2054 moveToTime(datetime);
2055 }
2056 else
2057 {
2059 }
2060 }
2061 else if (event->type() == UpdateGuideEvent::kEventType)
2062 {
2063 auto *uge = dynamic_cast<UpdateGuideEvent*>(event);
2064 if (uge && uge->m_updater)
2065 {
2066 uge->m_updater->ExecuteUI();
2067 delete uge->m_updater;
2068 uge->m_updater = nullptr;
2069 }
2070 }
2071}
2072
2074{
2075 if (m_dateText)
2077 if (m_longdateText)
2080}
2081
2082void GuideGrid::updateProgramsUI(unsigned int firstRow, unsigned int numRows,
2083 int progPast,
2084 const QVector<ProgramList*> &proglists,
2085 const ProgInfoGuideArray &programInfos,
2086 const std::list<GuideUIElement> &elements)
2087{
2088 for (unsigned int i = 0; i < numRows; ++i)
2089 {
2090 unsigned int row = i + firstRow;
2091 m_guideGrid->ResetRow(row);
2092 if (m_programs[row] != proglists[i])
2093 {
2094 delete m_programs[row];
2095 m_programs[row] = proglists[i];
2096 }
2097 }
2098 m_guideGrid->SetProgPast(progPast);
2099 for (const auto & r : elements)
2100 {
2101 m_guideGrid->SetProgramInfo(r.m_row, r.m_col, r.m_area, r.m_title,
2102 r.m_category, r.m_arrow, r.m_recType,
2103 r.m_recStat, r.m_selected);
2104 }
2105 for (unsigned int i = firstRow; i < firstRow + numRows; ++i)
2106 {
2107 for (int j = 0; j < MAX_DISPLAY_TIMES; ++j)
2108 m_programInfos[i][j] = programInfos[i][j];
2109 if (i == (unsigned int)m_currentRow)
2110 updateInfo();
2111 }
2113}
2114
2116{
2117 auto *updater = new GuideUpdateChannels(this, m_currentStartChannel);
2118 m_threadPool.start(new GuideHelper(this, updater), "GuideHelper");
2119}
2120
2121void GuideGrid::updateChannelsNonUI(QVector<ChannelInfo *> &chinfos,
2122 QVector<bool> &unavailables)
2123{
2125
2126 for (unsigned int y = 0; (y < (unsigned int)m_channelCount) && chinfo; ++y)
2127 {
2128 unsigned int chanNumber = y + m_currentStartChannel;
2129 if (chanNumber >= m_channelInfos.size())
2130 chanNumber -= m_channelInfos.size();
2131 if (chanNumber >= m_channelInfos.size())
2132 break;
2133
2134 chinfo = GetChannelInfo(chanNumber);
2135
2136 bool unavailable = false;
2137 bool try_alt = false;
2138
2139 if (m_player)
2140 {
2142 const PlayerContext* ctx = m_player->GetPlayerContext();
2143 if (ctx && chinfo)
2144 try_alt = !TV::IsTunable(chinfo->m_chanId);
2146 }
2147
2148 if (try_alt)
2149 {
2150 unavailable = true;
2151
2152 // Try alternates with same channum if applicable
2153 uint alt = GetAlternateChannelIndex(chanNumber, true);
2154 if (alt != m_channelInfoIdx[chanNumber])
2155 {
2156 unavailable = false;
2157 m_channelInfoIdx[chanNumber] = alt;
2158 chinfo = GetChannelInfo(chanNumber);
2159 }
2160
2161 // Try alternates with different channum if applicable
2162 if (unavailable && chinfo &&
2163 !GetProgramList(chinfo->m_chanId).empty())
2164 {
2165 alt = GetAlternateChannelIndex(chanNumber, false);
2166 unavailable = (alt == m_channelInfoIdx[chanNumber]);
2167 }
2168 }
2169 chinfos.push_back(chinfo);
2170 unavailables.push_back(unavailable);
2171 }
2172}
2173
2174void GuideGrid::updateChannelsUI(const QVector<ChannelInfo *> &chinfos,
2175 const QVector<bool> &unavailables)
2176{
2178 for (int i = 0; i < chinfos.size(); ++i)
2179 {
2180 ChannelInfo *chinfo = chinfos[i];
2181 bool unavailable = unavailables[i];
2182 auto *item = new MythUIButtonListItem(m_channelList,
2183 chinfo ? chinfo->GetFormatted(ChannelInfo::kChannelShort) : QString());
2184
2185 QString state = "available";
2186 if (unavailable)
2187 state = (m_changrpid == -1) ? "unavailable" : "favunavailable";
2188 else
2189 state = (m_changrpid == -1) ? "available" : "favourite";
2190
2191 item->SetFontState(state);
2192 item->DisplayState(state, "chanstatus");
2193
2194 if (chinfo)
2195 {
2196 InfoMap infomap;
2197 chinfo->ToMap(infomap);
2198 item->SetTextFromMap(infomap);
2199
2200 if (!chinfo->m_icon.isEmpty())
2201 {
2202 QString iconurl =
2203 gCoreContext->GetMasterHostPrefix("ChannelIcons",
2204 chinfo->m_icon);
2205 item->SetImage(iconurl, "channelicon");
2206 }
2207 }
2208 }
2210}
2211
2213{
2214 if (m_currentRow < 0 || m_currentCol < 0)
2215 return;
2216
2218 if (!pginfo)
2219 return;
2220
2221 InfoMap infoMap;
2222
2223 int chanNum = m_currentRow + m_currentStartChannel;
2224 if (chanNum >= (int)m_channelInfos.size())
2225 chanNum -= (int)m_channelInfos.size();
2226 if (chanNum >= (int)m_channelInfos.size())
2227 return;
2228 chanNum = std::max(chanNum, 0);
2229
2230 ChannelInfo *chinfo = GetChannelInfo(chanNum);
2231
2232 if (m_channelImage)
2233 {
2235 if (!chinfo->m_icon.isEmpty())
2236 {
2237 QString iconurl = gCoreContext->GetMasterHostPrefix("ChannelIcons",
2238 chinfo->m_icon);
2239
2240 m_channelImage->SetFilename(iconurl);
2242 }
2243 }
2244
2245 chinfo->ToMap(infoMap);
2246 pginfo->ToMap(infoMap);
2247 // HACK - This should be done in ProgramInfo, but that needs more careful
2248 // review since it may have unintended consequences so we're doing it here
2249 // for now
2250 if (infoMap["title"] == kUnknownTitle)
2251 {
2252 infoMap["title"] = tr("Unknown", "Unknown program title");
2253 infoMap["titlesubtitle"] = tr("Unknown", "Unknown program title");
2254 }
2255
2256 SetTextFromMap(infoMap);
2257
2258 MythUIStateType *ratingState = dynamic_cast<MythUIStateType*>
2259 (GetChild("ratingstate"));
2260 if (ratingState)
2261 {
2262 QString rating = QString::number(pginfo->GetStars(10));
2263 ratingState->DisplayState(rating);
2264 }
2266}
2267
2269{
2270 int oldchangrpid = m_changrpid;
2271
2273
2274 if (oldchangrpid != m_changrpid)
2276
2278 updateInfo();
2279
2280 QString changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
2281
2282 if (m_changroupname)
2283 m_changroupname->SetText(changrpname);
2284}
2285
2287{
2289 m_currentRow = 0;
2290
2291 int maxchannel = 0;
2293 maxchannel = std::max((int)GetChannelCount() - 1, 0);
2294 m_channelCount = std::min(m_guideGrid->getChannelCount(), maxchannel + 1);
2295
2298}
2299
2300// mode 0 Include empty channel groups
2301// mode 1 Exclude empty channel groups
2302// mode 2 Only Manual channel groups
2304{
2305 ChannelGroupList channels;
2306 if (mode == 2)
2307 channels = ChannelGroup::GetManualChannelGroups(true);
2308 else
2309 channels = ChannelGroup::GetChannelGroups(mode == 0);
2310
2311 if (channels.empty())
2312 {
2313 QString message = tr("You don't have any channel groups defined");
2314
2315 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2316
2317 auto *okPopup = new MythConfirmationDialog(popupStack, message, false);
2318 if (okPopup->Create())
2319 popupStack->AddScreen(okPopup);
2320 else
2321 delete okPopup;
2322
2323 return;
2324 }
2325
2326 QString label = tr("Select Channel Group");
2327
2328 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2329 auto *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
2330
2331 if (menuPopup->Create())
2332 {
2333 if (mode == 0 || mode == 2)
2334 {
2335 // add channel to group menu
2336 menuPopup->SetReturnEvent(this, "channelgrouptogglemenu");
2337 }
2338 else
2339 {
2340 // switch to channel group menu
2341 menuPopup->SetReturnEvent(this, "channelgroupmenu");
2342 menuPopup->AddButton(QObject::tr("All Channels"));
2343 }
2344
2345 for (auto & channel : channels)
2346 {
2347 menuPopup->AddButton(channel.m_name);
2348 }
2349
2350 popupStack->AddScreen(menuPopup);
2351 }
2352 else
2353 {
2354 delete menuPopup;
2355 }
2356}
2357
2359{
2361
2362 if (grpid == -1)
2363 {
2364 if (m_changrpid == -1)
2365 return;
2366 grpid = m_changrpid;
2367 }
2368
2369 // Get current channel id, and make sure it exists...
2370 int chanNum = m_currentRow + m_currentStartChannel;
2371 if (chanNum >= (int)m_channelInfos.size())
2372 chanNum -= (int)m_channelInfos.size();
2373 if (chanNum >= (int)m_channelInfos.size())
2374 return;
2375 chanNum = std::max(chanNum, 0);
2376
2377 ChannelInfo *ch = GetChannelInfo(chanNum);
2378 uint chanid = ch->m_chanId;
2379
2380 // All Channels plus all automatic channel groups
2382 {
2383 // If currently viewing all channels, allow to add only not delete
2384 ChannelGroup::ToggleChannel(chanid, grpid, false);
2385 }
2386 else
2387 {
2388 // Only allow delete if viewing the favorite group in question
2389 ChannelGroup::ToggleChannel(chanid, grpid, true);
2390 }
2391
2392 // Regenerate the list of non empty groups in case it did change
2394
2395 // If viewing a manual group such as Favorites, refresh because a channel was removed
2397 {
2400 updateInfo();
2401 }
2402}
2403
2405{
2407
2408 if (!test)
2409 {
2411 return;
2412 }
2413
2414 int8_t startCol = test->m_startCol;
2415 m_currentCol = startCol - 1;
2416
2417 if (m_currentCol < 0)
2418 {
2419 m_currentCol = 0;
2421 }
2422 else
2423 {
2425 }
2426}
2427
2429{
2431
2432 if (!test)
2433 {
2435 return;
2436 }
2437
2438 int8_t spread = test->m_spread;
2439 int8_t startCol = test->m_startCol;
2440
2441 m_currentCol = startCol + spread;
2442
2443 if (m_currentCol > m_timeCount - 1)
2444 {
2447 }
2448 else
2449 {
2451 }
2452}
2453
2455{
2456 m_currentRow++;
2457
2458 if (m_currentRow > m_channelCount - 1)
2459 {
2462 }
2463 else
2464 {
2466 }
2467}
2468
2470{
2471 m_currentRow--;
2472
2473 if (m_currentRow < 0)
2474 {
2475 m_currentRow = 0;
2477 }
2478 else
2479 {
2481 }
2482}
2483
2485{
2486 switch (movement)
2487 {
2488 case kScrollLeft :
2490 break;
2491 case kScrollRight :
2493 break;
2494 case kPageLeft :
2496 break;
2497 case kPageRight :
2499 break;
2500 case kDayLeft :
2502 break;
2503 case kDayRight :
2505 break;
2506 default :
2507 break;
2508 }
2509
2510 fillTimeInfos();
2513}
2514
2516{
2517 switch (movement)
2518 {
2519 case kScrollDown :
2521 break;
2522 case kScrollUp :
2524 break;
2525 case kPageDown :
2527 break;
2528 case kPageUp :
2530 break;
2531 default :
2532 break;
2533 }
2534
2537}
2538
2539void GuideGrid::moveToTime(const QDateTime& datetime)
2540{
2541 if (!datetime.isValid())
2542 return;
2543
2544 m_currentStartTime = datetime;
2545
2546 fillTimeInfos();
2549}
2550
2551void GuideGrid::setStartChannel(int newStartChannel)
2552{
2553 if (newStartChannel < 0)
2554 m_currentStartChannel = newStartChannel + GetChannelCount();
2555 else if (newStartChannel >= (int) GetChannelCount())
2556 m_currentStartChannel = newStartChannel - GetChannelCount();
2557 else
2558 m_currentStartChannel = newStartChannel;
2559}
2560
2562{
2563 if (m_allowFinder)
2565}
2566
2568{
2569 if (!m_player)
2570 return;
2571
2572 m_updateTimer->stop();
2573
2574 channelUpdate();
2575
2576 // Don't perform transition effects when guide is being used during playback
2577 GetScreenStack()->PopScreen(this, false);
2578
2579 epgIsVisibleCond.wakeAll();
2580}
2581
2583{
2584 // HACK: Do not allow exit if we have a popup menu open, not convinced
2585 // that this is the right solution
2586 if (GetMythMainWindow()->GetStack("popup stack")->TotalScreens() > 0)
2587 return;
2588
2589 m_updateTimer->stop();
2590
2591 // don't fade the screen if we are returning to the player
2592 if (m_player)
2593 GetScreenStack()->PopScreen(this, false);
2594 else
2595 GetScreenStack()->PopScreen(this, true);
2596
2597 epgIsVisibleCond.wakeAll();
2598}
2599
2601{
2603
2604 if (!pginfo || !pginfo->GetRecordingRuleID())
2605 return;
2606
2607 auto *record = new RecordingRule();
2608 if (!record->LoadByProgram(pginfo))
2609 {
2610 delete record;
2611 return;
2612 }
2613
2614 QString message = tr("Delete '%1' %2 rule?")
2615 .arg(record->m_title, toString(pginfo->GetRecordingRuleType()));
2616
2617 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2618
2619 auto *okPopup = new MythConfirmationDialog(popupStack, message, true);
2620
2621 okPopup->SetReturnEvent(this, "deleterule");
2622 okPopup->SetData(QVariant::fromValue(record));
2623
2624 if (okPopup->Create())
2625 popupStack->AddScreen(okPopup);
2626 else
2627 delete okPopup;
2628}
2629
2631{
2632 if (!m_player)
2633 return;
2634
2636
2637 if (!sel.empty())
2638 {
2640 m_player->ChangeChannel(sel);
2642 }
2643}
2644
2645void GuideGrid::GoTo(int start, int cur_row)
2646{
2647 setStartChannel(start);
2648 m_currentRow = cur_row % m_channelCount;
2652}
2653
2655{
2656 QString txt;
2657 {
2658 QMutexLocker locker(&m_jumpToChannelLock);
2659 if (m_jumpToChannel)
2660 txt = m_jumpToChannel->GetEntry();
2661 }
2662
2663 if (txt.isEmpty())
2664 return;
2665
2666 if (m_jumpToText)
2667 m_jumpToText->SetText(txt);
2668}
2669
2671{
2672 QMutexLocker locker(&m_jumpToChannelLock);
2673 m_jumpToChannel = ptr;
2674
2675 if (!m_jumpToChannel)
2676 {
2677 if (m_jumpToText)
2679
2681 }
2682}
2683
2685{
2686 GetMythMainWindow()->GetPaintWindow()->clearMask();
2687}
2688
2690{
2692 QRegion r1 = QRegion(m_area);
2693 QRegion r2 = QRegion(m_videoRect);
2694 GetMythMainWindow()->GetPaintWindow()->setMask(r1.xored(r2));
2695}
2696
2698{
2699 if (m_player)
2700 HideTVWindow();
2701
2703}
2704
2706{
2707 if (m_player)
2708 EmbedTVWindow();
2709
2711}
2712
2714{
2715 QString message = tr("Jump to a specific date and time in the guide");
2718
2719 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2720 auto *timedlg = new MythTimeInputDialog(popupStack, message, flags);
2721
2722 if (timedlg->Create())
2723 {
2724 timedlg->SetReturnEvent(this, "jumptotime");
2725 popupStack->AddScreen(timedlg);
2726 }
2727 else
2728 {
2729 delete timedlg;
2730 }
2731}
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:1798
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:41
static const Type kEventType
Definition: mythdialogbox.h:56
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:2539
bool m_sortReverse
Definition: guidegrid.h:260
void moveUpDown(MoveVector movement)
Definition: guidegrid.cpp:2515
MythUIText * m_jumpToText
Definition: guidegrid.h:293
ChannelGroupList m_changrplist
Definition: guidegrid.h:282
db_chan_list_list_t m_channelInfos
Definition: guidegrid.h:243
QDateTime m_lastTime
Definition: guidegrid.h:267
MythUIText * m_dateText
Definition: guidegrid.h:291
ProgInfoGuideArray m_programInfos
Definition: guidegrid.h:247
void Close() override
Definition: guidegrid.cpp:2582
void PlayerExiting(TV *Player)
Definition: guidegrid.cpp:528
void cursorUp()
Definition: guidegrid.cpp:2469
@ kScrollLeft
Definition: guidegrid.h:188
@ kPageRight
Definition: guidegrid.h:193
@ kScrollRight
Definition: guidegrid.h:189
@ kScrollDown
Definition: guidegrid.h:187
QString m_startChanNum
Definition: guidegrid.h:255
MythUIImage * m_channelImage
Definition: guidegrid.h:295
MythUIButtonList * m_channelList
Definition: guidegrid.h:289
void GoTo(int start, int cur_row) override
Definition: guidegrid.cpp:2645
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:288
QDateTime m_firstTime
Definition: guidegrid.h:266
ChannelGroupList m_channelGroupListManual
Definition: guidegrid.h:283
QRect m_videoRect
Definition: guidegrid.h:273
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:2286
ProgramList * getProgramListFromProgram(int chanNum)
Definition: guidegrid.cpp:1568
ProgramList m_recList
Definition: guidegrid.h:248
void updateChannelsUI(const QVector< ChannelInfo * > &chinfos, const QVector< bool > &unavailables)
Definition: guidegrid.cpp:2174
QRecursiveMutex m_jumpToChannelLock
Definition: guidegrid.h:285
QDateTime GetCurrentStartTime(void) const
Definition: guidegrid.h:132
void ShowMenu(void) override
Definition: guidegrid.cpp:1103
MythUIText * m_changroupname
Definition: guidegrid.h:294
~GuideGrid() override
Definition: guidegrid.cpp:631
void EmbedTVWindow(void)
Definition: guidegrid.cpp:2689
void deleteRule()
Definition: guidegrid.cpp:2600
int GetStartChannelOffset(int row=-1) const
Definition: guidegrid.cpp:1203
void updateChannelsNonUI(QVector< ChannelInfo * > &chinfos, QVector< bool > &unavailables)
Definition: guidegrid.cpp:2121
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:2082
void setStartChannel(int newStartChannel)
Definition: guidegrid.cpp:2551
void cursorRight()
Definition: guidegrid.cpp:2428
QMap< uint, uint > m_channelInfoIdx
Definition: guidegrid.h:244
void SetJumpToChannel(JumpToChannel *ptr) override
Definition: guidegrid.cpp:2670
uint m_startChanID
Definition: guidegrid.h:254
JumpToChannel * m_jumpToChannel
Definition: guidegrid.h:286
uint GetCurrentStartChannel(void) const
Definition: guidegrid.h:131
int m_currentCol
Definition: guidegrid.h:258
uint m_currentStartChannel
Definition: guidegrid.h:253
bool Create(void) override
Definition: guidegrid.cpp:539
std::vector< ProgramList * > m_programs
Definition: guidegrid.h:246
int FindChannel(uint chanid, const QString &channum, bool exact=true) const override
Definition: guidegrid.cpp:1469
void updateJumpToChannel(void)
Definition: guidegrid.cpp:2654
void updateChannels(void)
Definition: guidegrid.cpp:2115
void showProgFinder()
Definition: guidegrid.cpp:2561
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:257
QString m_channelOrdering
Definition: guidegrid.h:275
void aboutToShow() override
Definition: guidegrid.cpp:2705
void enter()
Definition: guidegrid.cpp:2567
bool m_embedVideo
Definition: guidegrid.h:270
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:242
ChannelInfo * GetChannelInfo(uint chan_idx, int sel=-1)
Definition: guidegrid.cpp:1180
void updateInfo(void)
Definition: guidegrid.cpp:2212
int m_channelCount
Definition: guidegrid.h:262
void toggleGuideListing()
Definition: guidegrid.cpp:2268
void ToggleMute(bool CycleChannels)
QDateTime m_currentEndTime
Definition: guidegrid.h:252
bool m_verticalLayout
Definition: guidegrid.h:264
void ShowJumpToTime(void)
Definition: guidegrid.cpp:2713
int m_changrpid
Definition: guidegrid.h:281
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:2684
void fillProgramRowInfos(int row, bool useExistingData)
Definition: guidegrid.cpp:1593
void ChannelGroupMenu(int mode=0)
Definition: guidegrid.cpp:2303
void fillProgramInfos(bool useExistingData=false)
Definition: guidegrid.cpp:1563
QTimer * m_updateTimer
Definition: guidegrid.h:277
int m_timeCount
Definition: guidegrid.h:263
void updateDateText(void)
Definition: guidegrid.cpp:2073
TV * m_player
Definition: guidegrid.h:269
ChannelInfoList GetSelection(void) const
Definition: guidegrid.cpp:1308
void customEvent(QEvent *event) override
Definition: guidegrid.cpp:1893
void cursorDown()
Definition: guidegrid.cpp:2454
MThreadPool m_threadPool
Definition: guidegrid.h:279
void cursorLeft()
Definition: guidegrid.cpp:2404
MythUIText * m_longdateText
Definition: guidegrid.h:292
QDateTime m_originalStartTime
Definition: guidegrid.h:250
void channelUpdate()
Definition: guidegrid.cpp:2630
QDateTime m_currentStartTime
Definition: guidegrid.h:251
void toggleChannelFavorite(int grpid=-1)
Definition: guidegrid.cpp:2358
void aboutToHide() override
Definition: guidegrid.cpp:2697
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:240
void moveLeftRight(MoveVector movement)
Definition: guidegrid.cpp:2484
MythUIGuideGrid * m_guideGrid
Definition: guidegrid.h:290
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:551
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:86
MythUIType * GetChildAt(QPoint p, bool recursive=true, bool focusable=true) const
Return the first MythUIType at the given coordinates.
Definition: mythuitype.cpp:226
void SetRedraw(void)
Definition: mythuitype.cpp:298
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:870
MythUIType * m_parent
Definition: mythuitype.h:297
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:129
MythRect m_area
Definition: mythuitype.h:277
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:156
void VolumeChange(bool Up, int NewVolume=-1)
Definition: tv_play.cpp:7022
static void SetActiveChannelGroupId(int channelgroupid)
Definition: tv_play.h:518
PlayerContext * GetPlayerContext()
Return a pointer to TV::m_playerContext.
Definition: tv_play.cpp:193
void GetPlayerReadLock() const
Definition: tv_play.cpp:10500
void PlaybackExiting(TV *Player)
static bool StartTV(ProgramInfo *TVRec, uint Flags, const ChannelInfoList &Selection=ChannelInfoList())
Start playback of media.
Definition: tv_play.cpp:287
static bool IsTunable(uint ChanId)
Definition: tv_play.cpp:6766
void ReturnPlayerLock() const
Definition: tv_play.cpp:10505
TVState GetState() const
Definition: tv_play.cpp:1370
void UpdateChannelList(int GroupID)
update the channel list with channels from the selected channel group
Definition: tv_play.cpp:1347
void ChangeChannel(const ChannelInfoList &Options)
Definition: tv_play.cpp:6242
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
STL namespace.
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:114
std::vector< uint > RemoteRequestFreeInputList(uint excluded_input)
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:86
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:80