12 #include <QCoreApplication>
37 #define LOC QString("GuideGrid: ")
38 #define LOC_ERR QString("GuideGrid, Error: ")
39 #define LOC_WARN QString("GuideGrid, Warning: ")
46 int start_chan_idx,
int cur_chan_idx,
uint rows_disp) :
49 m_previous_start_channel_index(start_chan_idx),
50 m_previous_current_channel_index(cur_chan_idx),
51 m_rows_displayed(rows_disp),
52 m_timer(new QTimer(this))
77 QObject::deleteLater();
83 QStringList::const_iterator it;
84 for (it = actions.begin(); it != actions.end(); ++it)
120 QString txt = e->text();
130 if (!
m_entry.isEmpty() && (txt==
"_" || txt==
"-" || txt==
"#" || txt==
"."))
168 const QDateTime startTime,
169 TV *player,
bool embedVideo,
170 bool allowFinder,
int changrpid)
178 0,
true,
"", (changrpid<0) ? 0 : changrpid);
179 if (channels.empty())
184 message = tr(
"You don't have any channels defined in the database."
185 "\n\t\t\tThe program guide will have nothing to show you.");
189 message = tr(
"Channel group '%1' doesn't have any channels defined."
190 "\n\t\t\tThe program guide will have nothing to show you.")
194 LOG(VB_GENERAL, LOG_WARNING,
LOC + message);
200 if (player && allowFinder)
202 message = QString(
"EPG_EXITING");
203 qApp->postEvent(player,
new MythEvent(message));
212 chanid, channum, startTime,
213 player, embedVideo, allowFinder,
217 mainStack->
AddScreen(gg, (player == NULL));
223 uint chanid, QString
channum,
const QDateTime startTime,
224 TV *player,
bool embedVideo,
225 bool allowFinder,
int changrpid)
227 m_allowFinder(allowFinder),
229 m_usingNullVideo(
false), m_embedVideo(embedVideo),
230 m_previewVideoRefreshTimer(new QTimer(this)),
232 m_jumpToChannelLock(QMutex::Recursive),
233 m_jumpToChannel(NULL)
249 for (
uint i = 0; i < MAX_DISPLAY_CHANS; i++)
252 for (
int x = 0;
x < MAX_DISPLAY_TIMES; ++
x)
254 for (
int y = 0;
y < MAX_DISPLAY_CHANS; ++
y)
259 if (startTime.isValid() &&
272 QString windowName =
"programguide";
275 windowName =
"programguide-video";
292 LOG(VB_GENERAL, LOG_ERR,
293 QString(
"Cannot load screen '%1'").arg(windowName));
397 QString message = QString(
"EPG_EXITING");
413 bool handled =
false;
425 QString chanNum = actions[0];
427 chanNum.toInt(&isNum);
449 for (
int i = 0; i < actions.size() && !handled; ++i)
451 QString
action = actions[i];
453 if (action == ACTION_UP)
460 else if (action == ACTION_DOWN)
467 else if (action == ACTION_LEFT)
474 else if (action == ACTION_RIGHT)
481 else if (action ==
"PAGEUP")
488 else if (action ==
"PAGEDOWN")
495 else if (action == ACTION_PAGELEFT)
502 else if (action == ACTION_PAGERIGHT)
509 else if (action == ACTION_DAYLEFT)
511 else if (action == ACTION_DAYRIGHT)
513 else if (action ==
"NEXTFAV")
515 else if (action == ACTION_FINDER)
517 else if (action ==
"MENU")
519 else if (action ==
"ESCAPE" || action == ACTION_GUIDE)
521 else if (action == ACTION_SELECT)
546 else if (action ==
"EDIT")
548 else if (action ==
"CUSTOMEDIT")
550 else if (action ==
"DELETE")
552 else if (action ==
"UPCOMING")
554 else if (action ==
"DETAILS" || action ==
"INFO")
556 else if (action == ACTION_TOGGLERECORD)
558 else if (action == ACTION_TOGGLEFAV)
565 else if (action ==
"CHANUPDATE")
567 else if (action == ACTION_VOLUMEUP)
569 else if (action == ACTION_VOLUMEDOWN)
571 else if (action ==
"CYCLEAUDIOCHAN")
573 else if (action == ACTION_MUTEAUDIO)
575 else if (action == ACTION_TOGGLEPGORDER)
593 QString label = tr(
"Guide Options");
604 menuPopup->
AddButton(tr(
"Change to Channel"));
608 menuPopup->
AddButton(tr(
"Recording Options"), NULL,
true);
610 menuPopup->
AddButton(tr(
"Program Details"));
612 menuPopup->
AddButton(tr(
"Jump to Time"), NULL,
true);
614 menuPopup->
AddButton(tr(
"Reverse Channel Order"));
618 menuPopup->
AddButton(tr(
"Choose Channel Group"));
621 menuPopup->
AddButton(tr(
"Add To Channel Group"), NULL,
true);
623 menuPopup->
AddButton(tr(
"Remove from Channel Group"), NULL,
true);
636 QString label = tr(
"Recording Options");
649 menuPopup->
AddButton(tr(
"Edit Recording Status"));
650 menuPopup->
AddButton(tr(
"Edit Schedule"));
651 menuPopup->
AddButton(tr(
"Show Upcoming"));
680 return ((
GuideGrid*)
this)->GetChannelInfo(chan_idx, sel);
703 "WHERE program.chanid = :CHANID AND "
704 " program.endtime >= :STARTTS AND "
705 " program.starttime <= :ENDTS AND "
706 " program.manualid = 0 ";
707 bindings[
":STARTTS"] =
711 bindings[
":CHANID"] = chanid;
720 uint chan_idx,
bool with_same_channum)
const
728 for (
uint i = 0; i < cnt; ++i)
739 if (with_same_channum != same_channum)
745 if (with_same_channum)
754 if (proglist.
empty() ||
755 proglist.
size() != ch_proglist.
size())
759 for (
uint j = 0; j < proglist.
size(); ++j)
761 isAlt &= proglist[j]->IsSameProgramTimeslot(*ch_proglist[j]);
777 #define MKKEY(IDX,SEL) ((((uint64_t)IDX) << 32) | SEL)
788 vector<uint64_t> sel;
789 sel.push_back( MKKEY(idx, si) );
795 selected.push_back(*ch);
801 if (proglist.
empty())
807 if (ci && (i != si) &&
810 sel.push_back( MKKEY(idx, i) );
817 if (ci && (i != si) &&
820 sel.push_back( MKKEY(idx, i) );
829 sel.push_back( MKKEY(idx, i) );
833 for (
uint i = 1; i < sel.size(); ++i)
838 if (!ci || proglist.
size() != ch_proglist.
size())
842 for (
uint j = 0; j < proglist.
size(); ++j)
844 isAlt &= proglist[j]->IsSameProgramTimeslot(*ch_proglist[j]);
872 typedef vector<uint> uint_list_t;
873 QMap<QString,uint_list_t> channum_to_index_map;
874 QMap<QString,uint_list_t> callsign_to_index_map;
876 for (
uint i = 0; i < channels.size(); ++i)
881 chan = channels.size() - i - 1;
884 bool ndup = channum_to_index_map[channels[chan].channum].size();
885 bool cdup = callsign_to_index_map[channels[chan].callsign].size();
902 for (
uint i = 0; i < channels.size(); ++i)
904 const uint_list_t &ndups = channum_to_index_map[channels[i].channum];
905 for (
uint j = 0; j < ndups.size(); ++j)
912 const uint_list_t &cdups = callsign_to_index_map[channels[i].callsign];
913 for (
uint j = 0; j < cdups.size(); ++j)
920 if (gotostartchannel)
928 LOG(VB_GENERAL, LOG_ERR,
"GuideGrid: "
929 "\n\t\t\tYou don't have any channels defined in the database."
930 "\n\t\t\tGuide grid will have nothing to show you.");
937 static QMutex chanSepRegExpLock;
978 if (exact || channum.isEmpty())
984 if (
m_channelInfos[i][0].channum.left(channum.length()) == channum)
993 if (
m_channelInfos[i][j].channum.left(channum.length()) == channum)
999 QMutexLocker locker(&chanSepRegExpLock);
1001 if (tmpchannum.contains(chanSepRegExp))
1003 tmpchannum.replace(chanSepRegExp,
"_");
1005 else if (channum.length() >= 2)
1007 tmpchannum = channum.left(channum.length() - 1) +
'_' +
1020 tmp.replace(chanSepRegExp,
"_");
1021 if (tmp == tmpchannum)
1040 int mins = starttime.time().minute();
1041 mins = 5 * (mins / 5);
1047 infomap[
"starttime"] = timeStr;
1049 QDateTime endtime = starttime.addSecs(60 * 30);
1059 starttime = starttime.addSecs(5 * 60);
1081 QString querystr =
"WHERE program.chanid = :CHANID "
1082 " AND program.endtime >= :STARTTS "
1083 " AND program.starttime <= :ENDTS "
1084 " AND program.manualid = 0 ";
1086 bindings[
":STARTTS"] =
1088 bindings[
":ENDTS"] =
1122 if (!useExistingData)
1145 progPast = played * 100 /
length;
1151 vector<ProgramInfo*> unknownlist;
1152 bool unknown =
false;
1156 if (program != proglist->
end() &&
1157 (ts >= (*program)->GetScheduledEndTime()))
1162 if ((program == proglist->
end()) ||
1163 (ts < (*program)->GetScheduledStartTime()))
1174 ts, ts.addSecs(5*60));
1175 unknownlist.push_back(proginfo);
1183 if (proginfo && proginfo == *program)
1199 ts = ts.addSecs(5 * 60);
1202 vector<ProgramInfo*>::iterator it = unknownlist.begin();
1203 for (; it != unknownlist.end(); ++it)
1209 double ydifference = 0.0, xdifference = 0.0;
1213 ydifference = programRect.width() /
1215 xdifference = programRect.height() /
1216 (double) m_timeCount;
1220 ydifference = programRect.height() /
1222 xdifference = programRect.width() /
1223 (double) m_timeCount;
1231 bool isCurrent =
false;
1248 if (pginfo->
spread != -1)
1264 for (
int z =
x + 1;
z <
x + spread; ++
z)
1277 tempRect = QRect((
int)(row * ydifference),
1278 (
int)(
x * xdifference),
1280 (
int)(xdifference * pginfo->
spread));
1284 tempRect = QRect((
int)(
x * xdifference),
1285 (
int)(row * ydifference),
1286 (
int)(xdifference * pginfo->
spread),
1291 if (tempRect.right() + 2 >= programRect.width())
1292 tempRect.setRight(programRect.width());
1293 if (tempRect.bottom() + 2 >= programRect.bottom())
1294 tempRect.setBottom(programRect.bottom());
1297 (m_currentCol < (
x + spread)))
1340 row, cnt, tempRect, pginfo->
GetTitle(),
1342 recStat, isCurrent);
1356 QString message = me->
Message();
1358 if (message ==
"SCHEDULE_CHANGE")
1364 else if (message ==
"STOP_VIDEO_REFRESH_TIMER")
1368 else if (message ==
"START_VIDEO_REFRESH_TIMER")
1377 QString resultid = dce->
GetId();
1381 if (resultid ==
"deleterule")
1384 qVariantValue<RecordingRule *>(dce->
GetData());
1387 if ((buttonnum > 0) && !record->
Delete())
1388 LOG(VB_GENERAL, LOG_ERR,
"Failed to delete recording rule");
1392 else if (resultid ==
"guidemenu")
1394 if (resulttext == tr(
"Record This"))
1398 else if (resulttext == tr(
"Change to Channel"))
1402 else if (resulttext == tr(
"Program Details"))
1406 else if (resulttext == tr(
"Reverse Channel Order"))
1412 else if (resulttext == tr(
"Add To Channel Group"))
1417 else if (resulttext == tr(
"Remove from Channel Group"))
1421 else if (resulttext == tr(
"Choose Channel Group"))
1425 else if (resulttext == tr(
"Recording Options"))
1429 else if (resulttext == tr(
"Jump to Time"))
1434 else if (resultid ==
"recmenu")
1436 if (resulttext == tr(
"Edit Recording Status"))
1440 else if (resulttext == tr(
"Edit Schedule"))
1444 else if (resulttext == tr(
"Show Upcoming"))
1448 else if (resulttext == tr(
"Custom Edit"))
1452 else if (resulttext == tr(
"Delete Rule"))
1458 else if (resultid ==
"channelgrouptogglemenu")
1463 if (changroupid > 0)
1466 else if (resultid ==
"channelgroupmenu")
1472 if (resulttext == QObject::tr(
"All Channels"))
1482 QString changrpname;
1489 else if (resultid ==
"jumptotime")
1491 QDateTime datetime = dce->
GetData().toDateTime();
1527 bool unavailable =
false, try_alt =
false;
1532 -1, __FILE__, __LINE__);
1546 unavailable =
false;
1552 if (unavailable && chinfo &&
1564 QString state =
"available";
1566 state = (
m_changrpid == -1) ?
"unavailable" :
"favunavailable";
1568 state = (
m_changrpid == -1) ?
"available" :
"favourite";
1576 chinfo->
ToMap(infomap);
1579 if (!chinfo->
icon.isEmpty())
1584 item->
SetImage(iconurl,
"channelicon");
1614 if (!chinfo->
icon.isEmpty())
1624 chinfo->
ToMap(infoMap);
1625 pginfo->
ToMap(infoMap);
1673 if (channels.empty())
1675 QString message = tr(
"You don't have any channel groups defined");
1689 QString label = tr(
"Select Channel Group");
1705 menuPopup->
AddButton(QObject::tr(
"All Channels"));
1708 for (
uint i = 0; i < channels.size(); ++i)
1800 int spread = test->
spread;
1915 if (!datetime.isValid())
1929 if (newStartChannel < 0)
2041 QString message = tr(
"Delete '%1' %2 rule?").arg(record->
m_title)
2050 okPopup->
SetData(qVariantFromValue(record));
2167 qApp->postEvent(
this, me);
2172 QRegion r1 = QRegion(
m_Area);
2179 me =
new MythEvent(
"START_VIDEO_REFRESH_TIMER");
2180 qApp->postEvent(
this, me);
2210 QString message = tr(
"Jump to a specific date and time in the guide");