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
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 }
2040 else if (resultid == "jumptotime")
2041 {
2042 QDateTime datetime = dce->GetData().toDateTime();
2043 moveToTime(datetime);
2044 }
2045 else
2046 {
2048 }
2049 }
2050 else if (event->type() == UpdateGuideEvent::kEventType)
2051 {
2052 auto *uge = dynamic_cast<UpdateGuideEvent*>(event);
2053 if (uge && uge->m_updater)
2054 {
2055 uge->m_updater->ExecuteUI();
2056 delete uge->m_updater;
2057 uge->m_updater = nullptr;
2058 }
2059 }
2060}
2061
2063{
2064 if (m_dateText)
2066 if (m_longdateText)
2069}
2070
2071void GuideGrid::updateProgramsUI(unsigned int firstRow, unsigned int numRows,
2072 int progPast,
2073 const QVector<ProgramList*> &proglists,
2074 const ProgInfoGuideArray &programInfos,
2075 const std::list<GuideUIElement> &elements)
2076{
2077 for (unsigned int i = 0; i < numRows; ++i)
2078 {
2079 unsigned int row = i + firstRow;
2080 m_guideGrid->ResetRow(row);
2081 if (m_programs[row] != proglists[i])
2082 {
2083 delete m_programs[row];
2084 m_programs[row] = proglists[i];
2085 }
2086 }
2087 m_guideGrid->SetProgPast(progPast);
2088 for (const auto & r : elements)
2089 {
2090 m_guideGrid->SetProgramInfo(r.m_row, r.m_col, r.m_area, r.m_title,
2091 r.m_category, r.m_arrow, r.m_recType,
2092 r.m_recStat, r.m_selected);
2093 }
2094 for (unsigned int i = firstRow; i < firstRow + numRows; ++i)
2095 {
2096 for (int j = 0; j < MAX_DISPLAY_TIMES; ++j)
2097 m_programInfos[i][j] = programInfos[i][j];
2098 if (i == (unsigned int)m_currentRow)
2099 updateInfo();
2100 }
2102}
2103
2105{
2106 auto *updater = new GuideUpdateChannels(this, m_currentStartChannel);
2107 m_threadPool.start(new GuideHelper(this, updater), "GuideHelper");
2108}
2109
2110void GuideGrid::updateChannelsNonUI(QVector<ChannelInfo *> &chinfos,
2111 QVector<bool> &unavailables)
2112{
2114
2115 for (unsigned int y = 0; (y < (unsigned int)m_channelCount) && chinfo; ++y)
2116 {
2117 unsigned int chanNumber = y + m_currentStartChannel;
2118 if (chanNumber >= m_channelInfos.size())
2119 chanNumber -= m_channelInfos.size();
2120 if (chanNumber >= m_channelInfos.size())
2121 break;
2122
2123 chinfo = GetChannelInfo(chanNumber);
2124
2125 bool unavailable = false;
2126 bool try_alt = false;
2127
2128 if (m_player)
2129 {
2131 const PlayerContext* ctx = m_player->GetPlayerContext();
2132 if (ctx && chinfo)
2133 try_alt = !TV::IsTunable(chinfo->m_chanId);
2135 }
2136
2137 if (try_alt)
2138 {
2139 unavailable = true;
2140
2141 // Try alternates with same channum if applicable
2142 uint alt = GetAlternateChannelIndex(chanNumber, true);
2143 if (alt != m_channelInfoIdx[chanNumber])
2144 {
2145 unavailable = false;
2146 m_channelInfoIdx[chanNumber] = alt;
2147 chinfo = GetChannelInfo(chanNumber);
2148 }
2149
2150 // Try alternates with different channum if applicable
2151 if (unavailable && chinfo &&
2152 !GetProgramList(chinfo->m_chanId).empty())
2153 {
2154 alt = GetAlternateChannelIndex(chanNumber, false);
2155 unavailable = (alt == m_channelInfoIdx[chanNumber]);
2156 }
2157 }
2158 chinfos.push_back(chinfo);
2159 unavailables.push_back(unavailable);
2160 }
2161}
2162
2163void GuideGrid::updateChannelsUI(const QVector<ChannelInfo *> &chinfos,
2164 const QVector<bool> &unavailables)
2165{
2167 for (int i = 0; i < chinfos.size(); ++i)
2168 {
2169 ChannelInfo *chinfo = chinfos[i];
2170 bool unavailable = unavailables[i];
2171 auto *item = new MythUIButtonListItem(m_channelList,
2172 chinfo ? chinfo->GetFormatted(ChannelInfo::kChannelShort) : QString());
2173
2174 QString state = "available";
2175 if (unavailable)
2176 state = (m_changrpid == -1) ? "unavailable" : "favunavailable";
2177 else
2178 state = (m_changrpid == -1) ? "available" : "favourite";
2179
2180 item->SetFontState(state);
2181 item->DisplayState(state, "chanstatus");
2182
2183 if (chinfo)
2184 {
2185 InfoMap infomap;
2186 chinfo->ToMap(infomap);
2187 item->SetTextFromMap(infomap);
2188
2189 if (!chinfo->m_icon.isEmpty())
2190 {
2191 QString iconurl =
2192 gCoreContext->GetMasterHostPrefix("ChannelIcons",
2193 chinfo->m_icon);
2194 item->SetImage(iconurl, "channelicon");
2195 }
2196 }
2197 }
2199}
2200
2202{
2203 if (m_currentRow < 0 || m_currentCol < 0)
2204 return;
2205
2207 if (!pginfo)
2208 return;
2209
2210 InfoMap infoMap;
2211
2212 int chanNum = m_currentRow + m_currentStartChannel;
2213 if (chanNum >= (int)m_channelInfos.size())
2214 chanNum -= (int)m_channelInfos.size();
2215 if (chanNum >= (int)m_channelInfos.size())
2216 return;
2217 chanNum = std::max(chanNum, 0);
2218
2219 ChannelInfo *chinfo = GetChannelInfo(chanNum);
2220
2221 if (m_channelImage)
2222 {
2224 if (!chinfo->m_icon.isEmpty())
2225 {
2226 QString iconurl = gCoreContext->GetMasterHostPrefix("ChannelIcons",
2227 chinfo->m_icon);
2228
2229 m_channelImage->SetFilename(iconurl);
2231 }
2232 }
2233
2234 chinfo->ToMap(infoMap);
2235 pginfo->ToMap(infoMap);
2236 // HACK - This should be done in ProgramInfo, but that needs more careful
2237 // review since it may have unintended consequences so we're doing it here
2238 // for now
2239 if (infoMap["title"] == kUnknownTitle)
2240 {
2241 infoMap["title"] = tr("Unknown", "Unknown program title");
2242 infoMap["titlesubtitle"] = tr("Unknown", "Unknown program title");
2243 }
2244
2245 SetTextFromMap(infoMap);
2246
2247 MythUIStateType *ratingState = dynamic_cast<MythUIStateType*>
2248 (GetChild("ratingstate"));
2249 if (ratingState)
2250 {
2251 QString rating = QString::number(pginfo->GetStars(10));
2252 ratingState->DisplayState(rating);
2253 }
2255}
2256
2258{
2259 int oldchangrpid = m_changrpid;
2260
2262
2263 if (oldchangrpid != m_changrpid)
2265
2267 updateInfo();
2268
2269 QString changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
2270
2271 if (m_changroupname)
2272 m_changroupname->SetText(changrpname);
2273}
2274
2276{
2278 m_currentRow = 0;
2279
2280 int maxchannel = 0;
2282 maxchannel = std::max((int)GetChannelCount() - 1, 0);
2283 m_channelCount = std::min(m_guideGrid->getChannelCount(), maxchannel + 1);
2284
2287}
2288
2289// mode 0 Include empty channel groups
2290// mode 1 Exclude empty channel groups
2291// mode 2 Only Manual channel groups
2293{
2294 ChannelGroupList channels;
2295 if (mode == 2)
2296 channels = ChannelGroup::GetManualChannelGroups(true);
2297 else
2298 channels = ChannelGroup::GetChannelGroups(mode == 0);
2299
2300 if (channels.empty())
2301 {
2302 QString message = tr("You don't have any channel groups defined");
2303
2304 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2305
2306 auto *okPopup = new MythConfirmationDialog(popupStack, message, false);
2307 if (okPopup->Create())
2308 popupStack->AddScreen(okPopup);
2309 else
2310 delete okPopup;
2311
2312 return;
2313 }
2314
2315 QString label = tr("Select Channel Group");
2316
2317 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2318 auto *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
2319
2320 if (menuPopup->Create())
2321 {
2322 if (mode == 0 || mode == 2)
2323 {
2324 // add channel to group menu
2325 menuPopup->SetReturnEvent(this, "channelgrouptogglemenu");
2326 }
2327 else
2328 {
2329 // switch to channel group menu
2330 menuPopup->SetReturnEvent(this, "channelgroupmenu");
2331 menuPopup->AddButton(QObject::tr("All Channels"));
2332 }
2333
2334 for (auto & channel : channels)
2335 {
2336 menuPopup->AddButton(channel.m_name);
2337 }
2338
2339 popupStack->AddScreen(menuPopup);
2340 }
2341 else
2342 {
2343 delete menuPopup;
2344 }
2345}
2346
2348{
2350
2351 if (grpid == -1)
2352 {
2353 if (m_changrpid == -1)
2354 return;
2355 grpid = m_changrpid;
2356 }
2357
2358 // Get current channel id, and make sure it exists...
2359 int chanNum = m_currentRow + m_currentStartChannel;
2360 if (chanNum >= (int)m_channelInfos.size())
2361 chanNum -= (int)m_channelInfos.size();
2362 if (chanNum >= (int)m_channelInfos.size())
2363 return;
2364 chanNum = std::max(chanNum, 0);
2365
2366 ChannelInfo *ch = GetChannelInfo(chanNum);
2367 uint chanid = ch->m_chanId;
2368
2369 // All Channels plus all automatic channel groups
2371 {
2372 // If currently viewing all channels, allow to add only not delete
2373 ChannelGroup::ToggleChannel(chanid, grpid, false);
2374 }
2375 else
2376 {
2377 // Only allow delete if viewing the favorite group in question
2378 ChannelGroup::ToggleChannel(chanid, grpid, true);
2379 }
2380
2381 // Regenerate the list of non empty groups in case it did change
2383
2384 // If viewing a manual group such as Favorites, refresh because a channel was removed
2386 {
2389 updateInfo();
2390 }
2391}
2392
2394{
2396
2397 if (!test)
2398 {
2400 return;
2401 }
2402
2403 int8_t startCol = test->m_startCol;
2404 m_currentCol = startCol - 1;
2405
2406 if (m_currentCol < 0)
2407 {
2408 m_currentCol = 0;
2410 }
2411 else
2412 {
2414 }
2415}
2416
2418{
2420
2421 if (!test)
2422 {
2424 return;
2425 }
2426
2427 int8_t spread = test->m_spread;
2428 int8_t startCol = test->m_startCol;
2429
2430 m_currentCol = startCol + spread;
2431
2432 if (m_currentCol > m_timeCount - 1)
2433 {
2436 }
2437 else
2438 {
2440 }
2441}
2442
2444{
2445 m_currentRow++;
2446
2447 if (m_currentRow > m_channelCount - 1)
2448 {
2451 }
2452 else
2453 {
2455 }
2456}
2457
2459{
2460 m_currentRow--;
2461
2462 if (m_currentRow < 0)
2463 {
2464 m_currentRow = 0;
2466 }
2467 else
2468 {
2470 }
2471}
2472
2474{
2475 switch (movement)
2476 {
2477 case kScrollLeft :
2479 break;
2480 case kScrollRight :
2482 break;
2483 case kPageLeft :
2485 break;
2486 case kPageRight :
2488 break;
2489 case kDayLeft :
2491 break;
2492 case kDayRight :
2494 break;
2495 default :
2496 break;
2497 }
2498
2499 fillTimeInfos();
2502}
2503
2505{
2506 switch (movement)
2507 {
2508 case kScrollDown :
2510 break;
2511 case kScrollUp :
2513 break;
2514 case kPageDown :
2516 break;
2517 case kPageUp :
2519 break;
2520 default :
2521 break;
2522 }
2523
2526}
2527
2528void GuideGrid::moveToTime(const QDateTime& datetime)
2529{
2530 if (!datetime.isValid())
2531 return;
2532
2533 m_currentStartTime = datetime;
2534
2535 fillTimeInfos();
2538}
2539
2540void GuideGrid::setStartChannel(int newStartChannel)
2541{
2542 if (newStartChannel < 0)
2543 m_currentStartChannel = newStartChannel + GetChannelCount();
2544 else if (newStartChannel >= (int) GetChannelCount())
2545 m_currentStartChannel = newStartChannel - GetChannelCount();
2546 else
2547 m_currentStartChannel = newStartChannel;
2548}
2549
2551{
2552 if (m_allowFinder)
2554}
2555
2557{
2558 if (!m_player)
2559 return;
2560
2561 m_updateTimer->stop();
2562
2563 channelUpdate();
2564
2565 // Don't perform transition effects when guide is being used during playback
2566 GetScreenStack()->PopScreen(this, false);
2567
2568 epgIsVisibleCond.wakeAll();
2569}
2570
2572{
2573 // HACK: Do not allow exit if we have a popup menu open, not convinced
2574 // that this is the right solution
2575 if (GetMythMainWindow()->GetStack("popup stack")->TotalScreens() > 0)
2576 return;
2577
2578 m_updateTimer->stop();
2579
2580 // don't fade the screen if we are returning to the player
2581 if (m_player)
2582 GetScreenStack()->PopScreen(this, false);
2583 else
2584 GetScreenStack()->PopScreen(this, true);
2585
2586 epgIsVisibleCond.wakeAll();
2587}
2588
2590{
2592
2593 if (!pginfo || !pginfo->GetRecordingRuleID())
2594 return;
2595
2596 auto *record = new RecordingRule();
2597 if (!record->LoadByProgram(pginfo))
2598 {
2599 delete record;
2600 return;
2601 }
2602
2603 QString message = tr("Delete '%1' %2 rule?")
2604 .arg(record->m_title, toString(pginfo->GetRecordingRuleType()));
2605
2606 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2607
2608 auto *okPopup = new MythConfirmationDialog(popupStack, message, true);
2609
2610 okPopup->SetReturnEvent(this, "deleterule");
2611 okPopup->SetData(QVariant::fromValue(record));
2612
2613 if (okPopup->Create())
2614 popupStack->AddScreen(okPopup);
2615 else
2616 delete okPopup;
2617}
2618
2620{
2621 if (!m_player)
2622 return;
2623
2625
2626 if (!sel.empty())
2627 {
2629 m_player->ChangeChannel(sel);
2631 }
2632}
2633
2634void GuideGrid::GoTo(int start, int cur_row)
2635{
2636 setStartChannel(start);
2637 m_currentRow = cur_row % m_channelCount;
2641}
2642
2644{
2645 QString txt;
2646 {
2647 QMutexLocker locker(&m_jumpToChannelLock);
2648 if (m_jumpToChannel)
2649 txt = m_jumpToChannel->GetEntry();
2650 }
2651
2652 if (txt.isEmpty())
2653 return;
2654
2655 if (m_jumpToText)
2656 m_jumpToText->SetText(txt);
2657}
2658
2660{
2661 QMutexLocker locker(&m_jumpToChannelLock);
2662 m_jumpToChannel = ptr;
2663
2664 if (!m_jumpToChannel)
2665 {
2666 if (m_jumpToText)
2668
2670 }
2671}
2672
2674{
2675 GetMythMainWindow()->GetPaintWindow()->clearMask();
2676}
2677
2679{
2681 QRegion r1 = QRegion(m_area);
2682 QRegion r2 = QRegion(m_videoRect);
2683 GetMythMainWindow()->GetPaintWindow()->setMask(r1.xored(r2));
2684}
2685
2687{
2688 if (m_player)
2689 HideTVWindow();
2690
2692}
2693
2695{
2696 if (m_player)
2697 EmbedTVWindow();
2698
2700}
2701
2703{
2704 QString message = tr("Jump to a specific date and time in the guide");
2707
2708 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2709 auto *timedlg = new MythTimeInputDialog(popupStack, message, flags);
2710
2711 if (timedlg->Create())
2712 {
2713 timedlg->SetReturnEvent(this, "jumptotime");
2714 popupStack->AddScreen(timedlg);
2715 }
2716 else
2717 {
2718 delete timedlg;
2719 }
2720}
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:1792
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:217
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:251
@ kChanOrderByChanNum
Definition: channelutil.h:208
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:2528
bool m_sortReverse
Definition: guidegrid.h:260
void moveUpDown(MoveVector movement)
Definition: guidegrid.cpp:2504
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:2571
void PlayerExiting(TV *Player)
Definition: guidegrid.cpp:528
void cursorUp()
Definition: guidegrid.cpp:2458
@ 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:2634
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:2275
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:2163
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:2678
void deleteRule()
Definition: guidegrid.cpp:2589
int GetStartChannelOffset(int row=-1) const
Definition: guidegrid.cpp:1203
void updateChannelsNonUI(QVector< ChannelInfo * > &chinfos, QVector< bool > &unavailables)
Definition: guidegrid.cpp:2110
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:2071
void setStartChannel(int newStartChannel)
Definition: guidegrid.cpp:2540
void cursorRight()
Definition: guidegrid.cpp:2417
QMap< uint, uint > m_channelInfoIdx
Definition: guidegrid.h:244
void SetJumpToChannel(JumpToChannel *ptr) override
Definition: guidegrid.cpp:2659
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:2643
void updateChannels(void)
Definition: guidegrid.cpp:2104
void showProgFinder()
Definition: guidegrid.cpp:2550
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:2694
void enter()
Definition: guidegrid.cpp:2556
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:2201
int m_channelCount
Definition: guidegrid.h:262
void toggleGuideListing()
Definition: guidegrid.cpp:2257
void ToggleMute(bool CycleChannels)
QDateTime m_currentEndTime
Definition: guidegrid.h:252
bool m_verticalLayout
Definition: guidegrid.h:264
void ShowJumpToTime(void)
Definition: guidegrid.cpp:2702
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:2673
void fillProgramRowInfos(int row, bool useExistingData)
Definition: guidegrid.cpp:1593
void ChannelGroupMenu(int mode=0)
Definition: guidegrid.cpp:2292
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:2062
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:2443
MThreadPool m_threadPool
Definition: guidegrid.h:279
void cursorLeft()
Definition: guidegrid.cpp:2393
MythUIText * m_longdateText
Definition: guidegrid.h:292
QDateTime m_originalStartTime
Definition: guidegrid.h:250
void channelUpdate()
Definition: guidegrid.cpp:2619
QDateTime m_currentStartTime
Definition: guidegrid.h:251
void toggleChannelFavorite(int grpid=-1)
Definition: guidegrid.cpp:2347
void aboutToHide() override
Definition: guidegrid.cpp:2686
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:2473
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:550
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:241
void SetRedraw(void)
Definition: mythuitype.cpp:313
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:885
MythUIType * m_parent
Definition: mythuitype.h:297
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:138
MythRect m_area
Definition: mythuitype.h:277
Holds information on recordings and videos.
Definition: programinfo.h:70
float GetStars(void) const
Definition: programinfo.h:448
uint GetRecordingRuleID(void) const
Definition: programinfo.h:455
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:400
void SetScheduledEndTime(const QDateTime &dt)
Definition: programinfo.h:531
QString GetTitle(void) const
Definition: programinfo.h:364
int8_t m_spread
Definition: programinfo.h:851
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:393
int8_t m_startCol
Definition: programinfo.h:852
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:453
QString GetCategory(void) const
Definition: programinfo.h:372
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:457
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:155
void VolumeChange(bool Up, int NewVolume=-1)
Definition: tv_play.cpp:7022
PlayerContext * GetPlayerContext()
Return a pointer to TV::m_playerContext.
Definition: tv_play.cpp:193
void GetPlayerReadLock() const
Definition: tv_play.cpp:10501
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:10506
TVState GetState() const
Definition: tv_play.cpp:1366
void UpdateChannelList(int GroupID)
update the channel list with channels from the selected channel group
Definition: tv_play.cpp:1343
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:68
static guint32 * tmp
Definition: goom_core.cpp:26
#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:939
AutoDeleteDeque< ProgramInfo * > ProgramList
Definition: programinfo.h:33
@ 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:113
std::vector< uint > RemoteRequestFreeInputList(uint excluded_input)
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89