30 LOG(VB_GENERAL, LOG_ERR,
"Cannot load 'Info buttonlist'");
41 QString table = (recorded) ?
"recordedrating" :
"programrating";
42 QString sel = QString(
43 "SELECT `system`, rating FROM %1 "
44 "WHERE chanid = :CHANID "
45 "AND starttime = :STARTTIME").arg(table);
58 QMap<QString,QString> main_ratings;
62 if (query.
value(0).toString().toLower() ==
"advisory")
64 advisory += query.
value(1).toString() +
", ";
67 main_ratings[query.
value(0).toString()] = query.
value(1).toString();
70 advisory = advisory.left(advisory.length() - 2);
72 if (main_ratings.empty())
75 if (!advisory.isEmpty())
76 advisory =
": " + advisory;
78 if (main_ratings.size() == 1)
80 return *main_ratings.begin() + advisory;
84 QMap<QString,QString>::const_iterator it;
85 for (it = main_ratings.cbegin(); it != main_ratings.cend(); ++it)
87 ratings += it.key() +
": " + *it +
", ";
90 return ratings +
"Advisory" + advisory;
125 for (
int i = 0; i < actions.size() && !handled; ++i)
127 const QString&
action = actions[i];
135 else if (
action ==
"DOWN")
163 using string_pair = QPair<QString, QString>;
164 QVector<string_pair> tests;
182 tests.append(qMakePair(QString(
"channel.recpriority"),
183 QString(
"channel.recpriority")));
184 tests.append(qMakePair(QString(
"capturecard.recpriority"),
185 QString(
"capturecard.recpriority")));
189 pwrpri = QString(
"(capturecard.cardid = record.prefinput) * %1")
191 tests.append(qMakePair(pwrpri, pwrpri));
195 pwrpri = QString(
"(program.hdtv > 0 OR "
196 "FIND_IN_SET('HDTV', program.videoprop) > 0) * %1")
198 tests.append(qMakePair(pwrpri, pwrpri));
203 (
"(FIND_IN_SET('WIDESCREEN', program.videoprop) > 0) * %1")
205 tests.append(qMakePair(pwrpri, pwrpri));
210 (
"(FIND_IN_SET('SIGNED', program.subtitletypes) > 0) * %1")
212 tests.append(qMakePair(pwrpri, pwrpri));
217 (
"(FIND_IN_SET('ONSCREEN', program.subtitletypes) > 0) * %1")
219 tests.append(qMakePair(pwrpri, pwrpri));
224 (
"(FIND_IN_SET('NORMAL', program.subtitletypes) > 0 OR "
225 "program.closecaptioned > 0 OR program.subtitled > 0) * %1")
227 tests.append(qMakePair(pwrpri, pwrpri));
232 (
"(FIND_IN_SET('HARDHEAR', program.subtitletypes) > 0 OR "
233 "FIND_IN_SET('HARDHEAR', program.audioprop) > 0) * %1")
235 tests.append(qMakePair(pwrpri, pwrpri));
240 (
"(FIND_IN_SET('VISUALIMPAIR', program.audioprop) > 0) * %1")
242 tests.append(qMakePair(pwrpri, pwrpri));
245 query.
prepare(
"SELECT recpriority, selectclause FROM powerpriority;");
255 int adj = query.
value(0).toInt();
258 QString sclause = query.
value(1).toString();
261 pwrpri = QString(
"(%1) * %2").arg(sclause)
262 .arg(query.
value(0).toInt());
263 pwrpri.replace(
"RECTABLE",
"record");
266 pwrpri += QString(
" AS powerpriority ");
268 tests.append(qMakePair(desc, pwrpri));
272 recmatch = QString(
"INNER JOIN record "
273 " ON ( record.recordid = %1 ) ")
276 for (
const auto & [label, csqlStart] : std::as_const(tests))
278 QString sqlStart = csqlStart;
279 query.
prepare(
"SELECT " + sqlStart.replace(
"program.",
"p.")
282 "INNER JOIN channel "
283 " ON ( channel.chanid = p.chanid ) "
284 "INNER JOIN capturecard "
285 " ON ( channel.sourceid = capturecard.sourceid AND "
286 " ( capturecard.schedorder <> 0 OR "
287 " capturecard.parentid = 0 ) ) ").arg(ptable)
289 "WHERE p.chanid = :CHANID AND"
290 " p.starttime = :STARTTIME ;");
295 adjustmsg = QString(
"%1 : ").arg(label);
298 int adj = query.
value(0).toInt();
301 adjustmsg += tr(
" MATCHED, adding %1").arg(adj);
306 adjustmsg += tr(
" not matched");
311 adjustmsg += tr(
" Query FAILED");
314 addItem(tr(
"Recording Priority Adjustment"), adjustmsg,
318 if (!tests.isEmpty())
319 addItem(tr(
"Priority Adjustment Total"), QString::number(total),
326 QString category_type;
329 QString syndicatedEpisodeNum;
332 QString title_pronounce;
340 bool recorded =
false;
352 QString ptable = recorded ?
"recordedprogram" :
"program";
356 query.
prepare(QString(
"SELECT category_type, airdate, stars,"
357 " partnumber, parttotal, audioprop+0, videoprop+0,"
358 " subtitletypes+0, syndicatedepisodenumber, generic,"
359 " showtype, colorcode, title_pronounce"
360 " FROM %1 WHERE chanid = :CHANID AND"
361 " starttime = :STARTTIME ;").arg(ptable));
368 category_type = query.
value(0).toString();
369 year = query.
value(1).toString();
370 stars = query.
value(2).toFloat();
371 partnumber = query.
value(3).toInt();
372 parttotal = query.
value(4).toInt();
373 audioprop = query.
value(5).toInt();
374 videoprop = query.
value(6).toInt();
375 subtype = query.
value(7).toInt();
376 syndicatedEpisodeNum = query.
value(8).toString();
377 generic = query.
value(9).toInt();
378 showtype = query.
value(10).toString();
379 colorcode = query.
value(11).toString();
380 title_pronounce = query.
value(12).toString();
397 category_type =
"movie";
399 category_type =
"series";
401 category_type =
"sports";
403 category_type =
"tvshow";
417 attr += tr(
"Part %1 of %2, ").arg(partnumber).arg(parttotal);
421 if (category_type ==
"movie")
430 attr += tr(
"%n star(s)",
"", roundf(stars * 10.0F)) +
", ";
432 if (!colorcode.isEmpty())
433 attr += colorcode +
", ";
435 if (audioprop & AUD_MONO)
436 attr += tr(
"Mono") +
", ";
437 if (audioprop & AUD_STEREO)
438 attr += tr(
"Stereo") +
", ";
439 if (audioprop & AUD_SURROUND)
440 attr += tr(
"Surround Sound") +
", ";
441 if (audioprop & AUD_DOLBY)
442 attr += tr(
"Dolby Sound") +
", ";
443 if (audioprop & AUD_HARDHEAR)
444 attr += tr(
"Audio for Hearing Impaired") +
", ";
445 if (audioprop & AUD_VISUALIMPAIR)
446 attr += tr(
"Audio for Visually Impaired") +
", ";
448 if (videoprop & VID_HDTV)
449 attr += tr(
"HDTV") +
", ";
450 if (videoprop & VID_WIDESCREEN)
451 attr += tr(
"Widescreen") +
", ";
452 if (videoprop & VID_AVC)
453 attr += tr(
"AVC/H.264") +
", ";
454 if (videoprop & VID_HEVC)
455 attr += tr(
"HEVC/H.265") +
", ";
456 if (videoprop & VID_720)
457 attr += tr(
"720p Resolution") +
", ";
459 if (videoprop & VID_PROGRESSIVE)
461 if (videoprop & VID_1080)
462 attr += tr(
"1080p Resolution") +
", ";
463 if (videoprop & VID_4K)
464 attr += tr(
"4K Resolution") +
", ";
468 if (videoprop & VID_1080)
469 attr += tr(
"1080i Resolution") +
", ";
470 if (videoprop & VID_4K)
471 attr += tr(
"4Ki Resolution") +
", ";
474 if (videoprop & VID_DAMAGED)
475 attr += tr(
"Damaged") +
", ";
477 if (subtype & SUB_HARDHEAR)
478 attr += tr(
"CC",
"Closed Captioned") +
", ";
479 if (subtype & SUB_NORMAL)
480 attr += tr(
"Subtitles Available") +
", ";
481 if (subtype & SUB_ONSCREEN)
482 attr += tr(
"Subtitled") +
", ";
483 if (subtype & SUB_SIGNED)
484 attr += tr(
"Deaf Signing") +
", ";
486 if (generic && category_type ==
"series")
487 attr += tr(
"Unidentified Episode") +
", ";
489 attr += tr(
"Repeat") +
", ";
493 attr.truncate(attr.lastIndexOf(
','));
494 s +=
" (" + attr +
")";
502 QString execProducers;
508 QString commentators;
511 using string_pair = QPair<QString, QString>;
512 QVector<string_pair> actor_list;
513 QVector<string_pair> guest_star_list;
514 QVector<string_pair> guest_list;
520 table =
"recordedcredits";
524 query.
prepare(QString(
"SELECT role, people.name, roles.name FROM %1"
526 " LEFT JOIN people ON"
527 " credits.person = people.person"
528 " LEFT JOIN roles ON"
529 " credits.roleid = roles.roleid"
530 " WHERE credits.chanid = :CHANID"
531 " AND credits.starttime = :STARTTIME"
532 " ORDER BY role, priority;").arg(table));
537 if (query.
exec() && query.
size() > 0)
547 role = query.
value(0).toString();
563 pname = QString::fromUtf8(query.
value(1)
564 .toByteArray().constData());
565 character = QString::fromUtf8(query.
value(2)
566 .toByteArray().constData());
568 if (!character.isEmpty())
571 actor_list.append(qMakePair(pname, character));
572 else if (role ==
"guest_star")
573 guest_star_list.append(qMakePair(pname, character));
574 else if (role ==
"guest")
575 guest_list.append(qMakePair(pname, character));
580 plist.removeDuplicates();
582 actors = plist.join(
", ");
583 else if (rstr ==
"director")
584 directors = plist.join(
", ");
585 else if (rstr ==
"producer")
586 producers = plist.join(
", ");
587 else if (rstr ==
"executive_producer")
588 execProducers = plist.join(
", ");
589 else if (rstr ==
"writer")
590 writers = plist.join(
", ");
591 else if (rstr ==
"guest_star")
592 guestStars = plist.join(
", ");
593 else if (rstr ==
"host")
594 hosts = plist.join(
", ");
595 else if (rstr ==
"adapter")
596 adapters = plist.join(
", ");
597 else if (rstr ==
"presenter")
598 presenters = plist.join(
", ");
599 else if (rstr ==
"commentator")
600 commentators = plist.join(
", ");
601 else if (rstr ==
"guest")
602 guests = plist.join(
", ");
610 plist.removeDuplicates();
612 actors = plist.join(
", ");
613 else if (rstr ==
"director")
614 directors = plist.join(
", ");
615 else if (rstr ==
"producer")
616 producers = plist.join(
", ");
617 else if (rstr ==
"executive_producer")
618 execProducers = plist.join(
", ");
619 else if (rstr ==
"writer")
620 writers = plist.join(
", ");
621 else if (rstr ==
"guest_star")
622 guestStars = plist.join(
", ");
623 else if (rstr ==
"host")
624 hosts = plist.join(
", ");
625 else if (rstr ==
"adapter")
626 adapters = plist.join(
", ");
627 else if (rstr ==
"presenter")
628 presenters = plist.join(
", ");
629 else if (rstr ==
"commentator")
630 commentators = plist.join(
", ");
631 else if (rstr ==
"guest")
632 guests = plist.join(
", ");
639 if (!actor_list.isEmpty())
641 for (
const auto & [actor, role] : std::as_const(actor_list))
644 if (!guest_star_list.isEmpty())
646 for (
const auto & [actor, role] : std::as_const(guest_star_list))
649 if (!guest_list.isEmpty())
651 for (
const auto & [actor, role] : std::as_const(guest_list))
667 query.
prepare(
"SELECT genre FROM programgenres "
668 "WHERE chanid = :CHANID AND starttime = :STARTTIME "
669 "AND relevance <> '0' ORDER BY relevance;");
680 s += query.
value(0).toString();
686 if (!category_type.isEmpty())
691 if (!showtype.isEmpty())
716 addItem(tr(
"Syndicated Episode Number"), syndicatedEpisodeNum,
721 category_type !=
"movie")
731 QDateTime statusDate;
743 query.
prepare(
"SELECT recstatus, starttime "
744 "FROM oldrecorded WHERE duplicate > 0 AND "
746 "((programid <> '' AND programid = :PROGRAMID) OR "
747 " (title <> '' AND title = :TITLE AND "
748 " subtitle <> '' AND subtitle = :SUBTITLE AND "
749 " description <> '' AND description = :DECRIPTION));");
760 else if (query.
next())
790 if (statusDate.isValid())
796 QString recordingRule;
797 QString lastRecorded;
798 QString nextRecording;
799 QString averageTimeShift;
800 QString watchListScore;
801 QString watchListStatus;
802 QString searchPhrase;
809 if (record && !record->
m_title.isEmpty())
810 recordingRule += QString(
" \"%2\"").arg(record->
m_title);
812 query.
prepare(
"SELECT last_record, next_record, avg_delay "
813 "FROM record WHERE recordid = :RECORDID");
818 if (query.
value(0).toDateTime().isValid())
824 if (query.
value(1).toDateTime().isValid())
830 if (query.
value(2).toInt() > 0)
831 averageTimeShift = tr(
"%n hour(s)",
"",
832 query.
value(2).toInt());
845 watchListStatus = tr(
"Auto-expire off");
848 watchListStatus = tr(
"Marked as 'watched'");
851 watchListStatus = tr(
"Not the earliest episode");
854 watchListStatus = tr(
"Recently deleted episode");
869 QDateTime fdate(QDate(1970, 1, 1),QTime(12,0,0));
883 QString recordingHost;
884 QString recordingInput;
886 QString recordedPathname;
887 QString recordedFilename;
888 QString recordedFileSize;
889 QString recordingGroup;
890 QString storageGroup;
891 QString playbackGroup;
892 QString recordingProfile;
902 recordedFileSize = QString(
"%1 ")
904 recordedFileSize += tr(
"GB",
"GigaBytes");
906 query.
prepare(
"SELECT profile FROM recorded"
907 " WHERE chanid = :CHANID"
908 " AND starttime = :STARTTIME;");
922 recordingProfile = record ? record->
m_recProfile : tr(
"Unknown");
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool isActive(void) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
int GetNumSetting(const QString &key, int defaultval=0)
static void DBError(const QString &where, const MSqlQuery &query)
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
void BuildFocusList(void)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
static QString getRatings(bool recorded, uint chanid, const QDateTime &startts)
void PowerPriorities(const QString &ptable)
void addItem(const QString &title, const QString &value, ProgInfoList::VisibleLevel level)
ProgInfoList::DataList m_data
bool Create(void) override
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
std::tuple< QString, QString, int > DataItem
bool Create(bool focusable)
Initialise buttonlist from XML.
void Display(const DataList &data)
Build list of key:value buttons.
bool Hide(void)
Remove infolist from display.
void Toggle(void)
Toggle infolist state. Focusable widgets toggle between Basic & Full info. Non-focusable widgets togg...
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
uint GetRecordingRuleID(void) const
QString GetBasename(void) const
QString GetSeriesID(void) const
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
uint GetEpisode(void) const
QString GetProgramID(void) const
QString GetRecordingGroup(void) const
uint GetRecordingID(void) const
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
bool IsRepeat(void) const
QString GetHostname(void) const
QString GetPlaybackGroup(void) const
QString GetDescription(void) const
QString GetStorageGroup(void) const
QString GetTitle(void) const
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
uint GetFindID(void) const
QString GetInputName(void) const
static QString i18n(const QString &msg)
Translations for play,recording, & storage groups +.
QString GetPathname(void) const
QDate GetOriginalAirDate(void) const
int GetRecordingPriority2(void) const
virtual uint64_t GetFilesize(void) const
RecStatus::Type GetRecordingStatus(void) const
QString GetSubtitle(void) const
QString GetCategory(void) const
uint GetSeason(void) const
RecordingType GetRecordingRuleType(void) const
uint GetEpisodeTotal(void) const
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
static const QRegularExpression kReLeadingAnd
Internal representation of a recording rule, mirrors the record table.
RecSearchType m_searchType
bool LoadByProgram(const ProgramInfo *proginfo)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MythMainWindow * GetMythMainWindow(void)
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
@ kDateFull
Default local time.
@ kAddYear
Add year to string if not included.
def rating(profile, smoonURL, gate)