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