8 #include <QCoreApplication>
26 #define LOC QString("ProgLister: ")
27 #define LOC_WARN QString("ProgLister, Warning: ")
28 #define LOC_ERR QString("ProgLister, Error: ")
31 const QString &view,
const QString &extraArg) :
37 m_startTime(MythDate::
current()),
38 m_searchTime(m_startTime),
39 m_channelOrdering(
gCoreContext->GetSetting(
"ChannelOrdering",
"channum")),
67 m_allowViewDialog(
true)
72 query.
prepare(
"SELECT COUNT(*) FROM program WHERE stars > 0");
76 if (query.
value(0).toInt() == 0)
104 m_startTime(MythDate::
current()),
105 m_searchTime(m_startTime),
106 m_channelOrdering(
gCoreContext->GetSetting(
"ChannelOrdering",
"channum")),
110 m_view(
"reverse time"),
130 m_positionText(NULL),
134 m_allowViewDialog(
true)
159 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'programlist'");
183 case plTitle: value = tr(
"Program Listings");
break;
190 case plSQLSearch: value = tr(
"Power Search");
break;
191 case plRecordid: value = tr(
"Rule Search");
break;
192 case plCategory: value = tr(
"Category Search");
break;
193 case plChannel: value = tr(
"Channel Search");
break;
194 case plMovies: value = tr(
"Movie Search");
break;
195 case plTime: value = tr(
"Time Search");
break;
197 default: value = tr(
"Unknown Search");
break;
219 QCoreApplication::postEvent(
this, slce);
237 "TV Frontend", e, actions);
239 bool needUpdate =
false;
240 for (
uint i = 0; i <
uint(actions.size()) && !handled; ++i)
242 QString
action = actions[i];
245 if (action ==
"PREVVIEW")
247 else if (action ==
"NEXTVIEW")
249 else if (action ==
"CUSTOMEDIT")
254 else if (action ==
"EDIT")
259 else if (action ==
"DELETE")
261 else if (action ==
"UPCOMING")
263 else if (action ==
"DETAILS" || action ==
"INFO")
265 else if (action ==
"GUIDE")
267 else if (action ==
"TOGGLERECORD")
269 else if (action ==
"1")
282 else if (action ==
"2")
315 sortMenu->
AddItem(tr(
"Reverse Sort Order"));
316 sortMenu->
AddItem(tr(
"Sort By Title"));
317 sortMenu->
AddItem(tr(
"Sort By Time"));
326 menu->
AddItem(tr(
"Sort"), NULL, sortMenu);
413 if (newview >= 0 && newview == oldview)
421 query.
prepare(
"DELETE FROM keyword "
422 "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
428 "ProgLister::updateKeywordInDB -- delete", query);
436 QString qphrase = text;
439 query.
prepare(
"REPLACE INTO keyword (phrase, searchtype)"
440 "VALUES(:PHRASE, :TYPE );");
446 "ProgLister::updateKeywordInDB -- replace", query);
458 bool connect_string =
true;
474 case plMovies: msg = tr(
"Select Rating");
break;
475 case plChannel: msg = tr(
"Select Channel");
break;
476 case plCategory: msg = tr(
"Select Category");
break;
479 .arg(tr(
"Select a search stored from"))
480 .arg(tr(
"Custom Record"));
break;
504 QString message = tr(
"Start search from date and time");
509 connect_string =
false;
531 connect(screen, SIGNAL(haveResult( QString)),
536 connect(screen, SIGNAL(haveResult( QDateTime)),
565 const QString &qphrase, QString &output,
MSqlBindings &bindings)
const
569 QStringList field = qphrase.split(
':');
570 if (field.size() != 6)
572 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Power search should have 6 fields," +
573 QString(
"\n\t\t\tnot %1 (%2)") .arg(field.size()).arg(qphrase));
577 static const QString bindinglist[6] =
587 static const QString outputlist[6] =
589 "program.title LIKE :POWERTITLE ",
590 "program.subtitle LIKE :POWERSUB ",
591 "program.description LIKE :POWERDESC ",
592 "program.category_type = :POWERCATTYPE ",
593 "programgenres.genre = :POWERGENRE ",
594 "channel.callsign = :POWERCALLSIGN ",
597 for (
uint i = 0; i < (
uint) field.size(); i++)
599 if (field[i].isEmpty())
602 if (!output.isEmpty())
605 output += outputlist[i];
606 bindings[bindinglist[i]] =
607 (!outputlist[i].contains(
"=")) ?
608 QString(
'%') + field[i] + QString(
'%') : field[i];
611 return output.contains(
"programgenres");
671 QString message = tr(
"Delete '%1' %2 rule?").arg(record->
m_title)
677 popupStack, message,
true);
680 okPopup->
SetData(qVariantFromValue(record));
695 QString message = tr(
"Delete this episode of '%1'?").arg(pi->
GetTitle());
708 "DELETE FROM oldrecorded "
709 "WHERE chanid = :CHANID AND "
710 " starttime = :STARTTIME");
728 QString message = tr(
"Delete all episodes of '%1'?").arg(pi->
GetTitle());
740 query.
prepare(
"DELETE FROM oldrecorded "
741 "WHERE title = :TITLE AND future = 0");
766 message +=
"\n\n\n" + tr(
"NOTE: removing items from this list will not "
767 "delete any recordings.");
769 QString title = tr(
"Previously Recorded");
773 menu->
AddItem(tr(
"Allow this episode to re-record"));
775 menu->
AddItem(tr(
"Never record this episode"));
776 menu->
AddItem(tr(
"Remove this episode from the list"));
777 menu->
AddItem(tr(
"Remove all episodes for this title"));
815 0,
true,
"channum, chanid");
818 for (
uint i = 0; i < channels.size(); ++i)
822 m_viewList.push_back(QString::number(channels[i].chanid));
831 QDateTime query_starttime =
m_startTime.addSecs(50 -
834 query.
prepare(
"SELECT g1.genre, g2.genre "
836 "JOIN programgenres g1 ON "
837 " program.chanid = g1.chanid AND "
838 " program.starttime = g1.starttime "
839 "LEFT JOIN programgenres g2 ON "
840 " g1.chanid = g2.chanid AND "
841 " g1.starttime = g2.starttime "
842 "WHERE program.endtime > :PGILSTART "
843 "GROUP BY g1.genre, g2.genre;");
844 query.
bindValue(
":PGILSTART", query_starttime);
856 QString genre1 = query.
value(0).toString();
857 if (genre1.isEmpty())
860 if (genre1 != lastGenre1)
867 QString genre2 = query.
value(1).toString();
868 if (genre2.isEmpty() || genre2 == genre1)
871 m_viewList.push_back(genre1 +
":/:" + genre2);
878 query.
prepare(
"SELECT category "
880 "WHERE program.endtime > :PGILSTART "
881 "GROUP BY category");
882 query.
bindValue(
":PGILSTART", query_starttime);
888 QString category = query.
value(0).toString();
889 if (category.isEmpty())
891 category = query.
value(0).toString();
905 query.
prepare(
"SELECT phrase FROM keyword "
906 "WHERE searchtype = :SEARCHTYPE;");
917 QString phrase = QString::fromUtf8(query.
value(0)
918 .toByteArray().constData());
919 if (phrase.isEmpty())
932 QString qphrase = view;
935 query.
prepare(
"REPLACE INTO keyword (phrase, searchtype)"
936 "VALUES(:VIEW, :SEARCHTYPE );");
941 "replace keyword", query);
995 for (
int i = 9; i > 0; i--)
997 float stars = i / 10.0;
998 m_viewList.push_back(QString(
">= %1").arg(stars));
1002 if (!view.isEmpty())
1023 query.
prepare(
"SELECT title FROM record "
1024 "WHERE recordid = :RECORDID");
1029 QString title = query.
value(0).toString();
1030 title = query.
value(0).toString();
1038 query.
prepare(
"SELECT rulename FROM customexample "
1039 "WHERE search > 0 ORDER BY rulename;");
1043 while (query.
next())
1045 QString rulename = query.
value(0).toString();
1046 if (rulename.isEmpty() || rulename.trimmed().isEmpty())
1048 rulename = query.
value(0).toString();
1053 if (!view.isEmpty())
1070 if (!view.isEmpty())
1078 class plCompare : binary_function<const ProgramInfo*, const ProgramInfo*, bool>
1170 bindings[
":PGILSTART"] =
1175 where =
"WHERE channel.visible = 1 "
1176 " AND program.endtime > :PGILSTART "
1177 " AND (program.title = :PGILPHRASE0 OR "
1178 " (program.seriesid <> '' AND "
1179 " program.seriesid = :PGILPHRASE1)) ";
1180 bindings[
":PGILPHRASE0"] = qphrase;
1185 where =
"LEFT JOIN oldprogram ON "
1186 " oldprogram.oldtitle = program.title "
1187 "WHERE channel.visible = 1 "
1188 " AND program.endtime > :PGILSTART "
1189 " AND oldprogram.oldtitle IS NULL "
1190 " AND program.manualid = 0 ";
1192 if (qphrase ==
"premieres")
1195 where +=
" ( program.originalairdate = DATE(";
1196 where +=
" CONVERT_TZ(program.starttime, 'UTC', 'SYSTEM'))";
1197 where +=
" AND (program.category = 'Special' ";
1198 where +=
" OR program.programid LIKE 'EP%0001')) ";
1199 where +=
" OR (program.category_type='movie' ";
1200 where +=
" AND program.stars > 0.5 ";
1201 where +=
" AND program.airdate >= YEAR(NOW()) - 2) ";
1204 else if (qphrase ==
"movies")
1206 where +=
" AND program.category_type = 'movie' ";
1208 else if (qphrase ==
"series")
1210 where +=
" AND program.category_type = 'series' ";
1212 else if (qphrase ==
"specials")
1214 where +=
" AND program.category_type = 'tvshow' ";
1218 where +=
" AND (program.category_type <> 'movie' ";
1219 where +=
" OR program.airdate >= YEAR(NOW()) - 3) ";
1224 where =
"WHERE channel.visible = 1 "
1225 " AND program.endtime > :PGILSTART "
1226 " AND program.title LIKE :PGILLIKEPHRASE0 ";
1227 bindings[
":PGILLIKEPHRASE0"] = QString(
"%") + qphrase +
'%';
1231 where =
"WHERE channel.visible = 1 "
1232 " AND program.endtime > :PGILSTART "
1233 " AND (program.title LIKE :PGILLIKEPHRASE1 "
1234 " OR program.subtitle LIKE :PGILLIKEPHRASE2 "
1235 " OR program.description LIKE :PGILLIKEPHRASE3 ) ";
1236 bindings[
":PGILLIKEPHRASE1"] = QString(
"%") + qphrase +
'%';
1237 bindings[
":PGILLIKEPHRASE2"] = QString(
"%") + qphrase +
'%';
1238 bindings[
":PGILLIKEPHRASE3"] = QString(
"%") + qphrase +
'%';
1242 where =
", people, credits WHERE channel.visible = 1 "
1243 " AND program.endtime > :PGILSTART "
1244 " AND people.name LIKE :PGILPHRASE1 "
1245 " AND credits.person = people.person "
1246 " AND program.chanid = credits.chanid "
1247 " AND program.starttime = credits.starttime";
1248 bindings[
":PGILPHRASE1"] = qphrase;
1257 if (!powerWhere.isEmpty())
1260 where = QString(
"LEFT JOIN programgenres ON "
1261 "program.chanid = programgenres.chanid AND "
1262 "program.starttime = programgenres.starttime ");
1264 where += QString(
"WHERE channel.visible = 1 "
1265 " AND program.endtime > :PGILSTART "
1266 " AND ( ") + powerWhere +
" ) ";
1272 qphrase.remove(QRegExp(
"^\\s*AND\\s+", Qt::CaseInsensitive));
1273 where = QString(
"WHERE channel.visible = 1 "
1274 " AND program.endtime > :PGILSTART "
1275 " AND ( %1 ) ").arg(qphrase);
1281 where =
"WHERE channel.visible = 1 "
1282 " AND program.endtime > :PGILSTART "
1283 " AND channel.chanid = :PGILPHRASE2 ";
1284 bindings[
":PGILPHRASE2"] = qphrase;
1290 where =
"WHERE channel.visible = 1 "
1291 " AND program.endtime > :PGILSTART "
1292 " AND program.category = :PGILPHRASE3 ";
1293 bindings[
":PGILPHRASE3"] = qphrase;
1297 where =
"JOIN programgenres g ON "
1298 " program.chanid = g.chanid AND "
1299 " program.starttime = g.starttime AND "
1300 " genre = :PGILPHRASE4 "
1301 "WHERE channel.visible = 1 "
1302 " AND program.endtime > :PGILSTART ";
1303 bindings[
":PGILPHRASE4"] = qphrase;
1307 where =
"JOIN programgenres g1 ON "
1308 " program.chanid = g1.chanid AND "
1309 " program.starttime = g1.starttime AND "
1310 " g1.genre = :GENRE1 "
1311 "JOIN programgenres g2 ON "
1312 " program.chanid = g2.chanid AND "
1313 " program.starttime = g2.starttime AND "
1314 " g2.genre = :GENRE2 "
1315 "WHERE channel.visible = 1 "
1316 " AND program.endtime > :PGILSTART ";
1323 where =
"WHERE channel.visible = 1 "
1324 " AND program.endtime > :PGILSTART "
1325 " AND program.category_type = 'movie' "
1326 " AND program.stars " + qphrase +
' ';
1331 searchTime.setTime(QTime(searchTime.time().hour(), 0, 0));
1332 bindings[
":PGILSEARCHTIME1"] = searchTime;
1333 where =
"WHERE channel.visible = 1 "
1334 " AND program.starttime >= :PGILSEARCHTIME1 ";
1337 where +=
" AND program.starttime < DATE_ADD(:PGILSEARCHTIME2, "
1338 "INTERVAL '1' HOUR) ";
1339 bindings[
":PGILSEARCHTIME2"] = bindings[
":PGILSEARCHTIME1"];
1344 where =
"JOIN recordmatch ON "
1345 " (program.starttime = recordmatch.starttime "
1346 " AND program.chanid = recordmatch.chanid) "
1347 "WHERE channel.visible = 1 "
1348 " AND program.endtime > :PGILSTART "
1349 " AND recordmatch.recordid = :PGILPHRASE5 ";
1350 bindings[
":PGILPHRASE5"] = qphrase;
1355 query.
prepare(
"SELECT fromclause, whereclause FROM customexample "
1356 "WHERE rulename = :RULENAME;");
1361 QString fromc = query.
value(0).toString();
1362 QString wherec = query.
value(1).toString();
1364 where = QString(
"WHERE channel.visible = 1 "
1365 " AND program.endtime > :PGILSTART "
1366 " AND ( %1 ) ").arg(wherec);
1367 if (!fromc.isEmpty())
1368 where = fromc +
' ' + where;
1375 where = QString(
"AND ( recordid = %1 OR title = :MTITLE )")
1377 bindings[
":MTITLE"] =
m_title;
1381 where = QString(
"AND title = :MTITLE ");
1382 bindings[
":MTITLE"] =
m_title;
1386 where = QString(
"AND recordid = %1 ").arg(
m_recid);
1394 selected = *selectedP;
1395 selectedP = &selected;
1417 const QRegExp prefixes(
1418 tr(
"^(The |A |An )",
1419 "Regular Expression for what to ignore when sorting"));
1437 if ((*it)->sortTitle != curtitle)
1439 curtitle = (*it)->sortTitle;
1494 pginfo.
ToMap(infoMap);
1540 dobreak = comp->operator()(selected,
m_itemList[i]);
1542 dobreak = comp->operator()(
m_itemList[i], selected);
1556 if (item->
GetText(
"is_item_initialized").isNull())
1559 pginfo->
ToMap(infoMap);
1570 if (tempSubTitle.trimmed().isEmpty())
1572 item->
SetText(tempSubTitle,
"titlesubtitle", state);
1581 item->
SetText(
"yes",
"is_item_initialized");
1595 tr(
"%1 of %2",
"Current position in list where %1 is the "
1596 "position, %2 is the total count")
1618 pginfo->
ToMap(infoMap);
1624 tr(
"%1 of %2",
"Current position in list where %1 is the "
1625 "position, %2 is the total count")
1642 bool needUpdate =
false;
1648 QString resultid = dce->
GetId();
1652 if (resultid ==
"sortmenu")
1672 else if (resultid ==
"deletemenu")
1698 else if (resultid ==
"deleterule")
1701 qVariantValue<RecordingRule *>(dce->
GetData());
1702 if (record && buttonnum > 0 && !record->
Delete())
1704 LOG(VB_GENERAL, LOG_ERR,
LOC +
1705 "Failed to delete recording rule");
1718 QString
id = slce->
GetId();
1720 if (
id == objectName())
1732 QString message = me->
Message();
1736 else if (message ==
"SCHEDULE_CHANGE")