MythTV  master
progdetails.cpp
Go to the documentation of this file.
1 
2 // qt
3 #include <QKeyEvent>
4 #include <QFile>
5 #include <QTextStream>
6 
7 // myth
8 #include "mythcorecontext.h"
9 #include "mythdialogbox.h"
10 #include "recordingrule.h"
11 #include "mythdb.h"
12 #include "mythuihelper.h"
13 #include "mythmainwindow.h"
14 
15 #include "progdetails.h"
16 #include "mythdate.h"
17 
18 #define LASTPAGE 2
19 
21 {
22  // Load the theme for this screen
23  bool foundtheme = LoadWindowFromXML("schedule-ui.xml", "programdetails", this);
24  if (!foundtheme)
25  return false;
26 
27  // Initialise details list
28  if (!m_infoList.Create(true))
29  {
30  LOG(VB_GENERAL, LOG_ERR, "Cannot load 'Info buttonlist'");
31  return false;
32  }
33 
35 
36  return true;
37 }
38 
39 QString ProgDetails::getRatings(bool recorded, uint chanid, const QDateTime& startts)
40 {
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);
46 
48  query.prepare(sel);
49  query.bindValue(":CHANID", chanid);
50  query.bindValue(":STARTTIME", startts);
51 
52  if (!query.exec() || !query.isActive())
53  {
54  MythDB::DBError("ProgDetails::getRatings", query);
55  return "";
56  }
57 
58  QMap<QString,QString> main_ratings;
59  QString advisory;
60  while (query.next())
61  {
62  if (query.value(0).toString().toLower() == "advisory")
63  {
64  advisory += query.value(1).toString() + ", ";
65  continue;
66  }
67  main_ratings[query.value(0).toString()] = query.value(1).toString();
68  }
69 
70  advisory = advisory.left(advisory.length() - 2);
71 
72  if (main_ratings.empty())
73  return advisory;
74 
75  if (!advisory.isEmpty())
76  advisory = ": " + advisory;
77 
78  if (main_ratings.size() == 1)
79  {
80  return *main_ratings.begin() + advisory;
81  }
82 
83  QString ratings;
84  QMap<QString,QString>::const_iterator it;
85  for (it = main_ratings.begin(); it != main_ratings.end(); ++it)
86  {
87  ratings += it.key() + ": " + *it + ", ";
88  }
89 
90  return ratings + "Advisory" + advisory;
91 }
92 
94 {
95  m_infoList.Hide();
96 }
97 
99 {
100  updatePage();
101 }
102 
104 {
105  if (m_data.isEmpty())
106  loadPage();
107 
109 }
110 
111 void ProgDetails::addItem(const QString &title, const QString &value,
113 {
114  if (value.isEmpty())
115  return;
116  ProgInfoList::DataItem item = std::make_tuple(title, value, level);
117  m_data.append(item);
118 }
119 
120 bool ProgDetails::keyPressEvent(QKeyEvent *event)
121 {
122  bool handled;
123  QStringList actions;
124  handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
125 
126  for (int i = 0; i < actions.size() && !handled; i++)
127  {
128  QString action = actions[i];
129  handled = true;
130 
131  if (action == "INFO" || action == "SELECT")
132  {
133  m_infoList.Toggle();
134  updatePage();
135  }
136  else if (action == "DOWN")
137  {
139  }
140  else if (action == "UP")
141  {
142  m_infoList.PageUp();
143  }
144  else
145  handled = false;
146  }
147 
148  if (!handled && MythScreenType::keyPressEvent(event))
149  handled = true;
150 
151  return handled;
152 }
153 
154 void ProgDetails::PowerPriorities(const QString & ptable)
155 {
156  int recordid = m_progInfo.GetRecordingRuleID();
157 
158  // If not a scheduled recording, abort .... ?
159  if (!recordid)
160  return;
161 
162  using string_pair = QPair<QString, QString>;
163  QList<string_pair > tests;
164  QList<string_pair >::iterator Itest;
165  QString recmatch;
166  QString pwrpri;
167  QString desc;
168  QString adjustmsg;
169  int adj;
170  int total = 0;
171 
172  MSqlQuery query(MSqlQuery::InitCon());
173 
174  int prefinputpri = gCoreContext->GetNumSetting("PrefInputPriority", 2);
175  int hdtvpriority = gCoreContext->GetNumSetting("HDTVRecPriority", 0);
176  int wspriority = gCoreContext->GetNumSetting("WSRecPriority", 0);
177  int slpriority = gCoreContext->GetNumSetting("SignLangRecPriority", 0);
178  int onscrpriority = gCoreContext->GetNumSetting("OnScrSubRecPriority", 0);
179  int ccpriority = gCoreContext->GetNumSetting("CCRecPriority", 0);
180  int hhpriority = gCoreContext->GetNumSetting("HardHearRecPriority", 0);
181  int adpriority = gCoreContext->GetNumSetting("AudioDescRecPriority", 0);
182 
183  tests.append(qMakePair(QString("channel.recpriority"),
184  QString("channel.recpriority")));
185  tests.append(qMakePair(QString("capturecard.recpriority"),
186  QString("capturecard.recpriority")));
187 
188  if (recordid && prefinputpri)
189  {
190  pwrpri = QString("(capturecard.cardid = record.prefinput) * %1")
191  .arg(prefinputpri);
192  tests.append(qMakePair(pwrpri, pwrpri));
193  }
194  if (hdtvpriority)
195  {
196  pwrpri = QString("(program.hdtv > 0 OR "
197  "FIND_IN_SET('HDTV', program.videoprop) > 0) * %1")
198  .arg(hdtvpriority);
199  tests.append(qMakePair(pwrpri, pwrpri));
200  }
201  if (wspriority)
202  {
203  pwrpri = QString
204  ("(FIND_IN_SET('WIDESCREEN', program.videoprop) > 0) * %1")
205  .arg(wspriority);
206  tests.append(qMakePair(pwrpri, pwrpri));
207  }
208  if (slpriority)
209  {
210  pwrpri = QString
211  ("(FIND_IN_SET('SIGNED', program.subtitletypes) > 0) * %1")
212  .arg(slpriority);
213  tests.append(qMakePair(pwrpri, pwrpri));
214  }
215  if (onscrpriority)
216  {
217  pwrpri = QString
218  ("(FIND_IN_SET('ONSCREEN', program.subtitletypes) > 0) * %1")
219  .arg(onscrpriority);
220  tests.append(qMakePair(pwrpri, pwrpri));
221  }
222  if (ccpriority)
223  {
224  pwrpri = QString
225  ("(FIND_IN_SET('NORMAL', program.subtitletypes) > 0 OR "
226  "program.closecaptioned > 0 OR program.subtitled > 0) * %1")
227  .arg(ccpriority);
228  tests.append(qMakePair(pwrpri, pwrpri));
229  }
230  if (hhpriority)
231  {
232  pwrpri = QString
233  ("(FIND_IN_SET('HARDHEAR', program.subtitletypes) > 0 OR "
234  "FIND_IN_SET('HARDHEAR', program.audioprop) > 0) * %1")
235  .arg(hhpriority);
236  tests.append(qMakePair(pwrpri, pwrpri));
237  }
238  if (adpriority)
239  {
240  pwrpri = QString
241  ("(FIND_IN_SET('VISUALIMPAIR', program.audioprop) > 0) * %1")
242  .arg(adpriority);
243  tests.append(qMakePair(pwrpri, pwrpri));
244  }
245 
246  query.prepare("SELECT recpriority, selectclause FROM powerpriority;");
247 
248  if (!query.exec())
249  {
250  MythDB::DBError("Power Priority", query);
251  return;
252  }
253 
254  while (query.next())
255  {
256  adj = query.value(0).toInt();
257  if (adj)
258  {
259  QString sclause = query.value(1).toString();
260  sclause.remove(QRegExp("^\\s*AND\\s+", Qt::CaseInsensitive));
261  sclause.remove(';');
262  pwrpri = QString("(%1) * %2").arg(sclause)
263  .arg(query.value(0).toInt());
264  if (!recordid && pwrpri.indexOf("RECTABLE") != -1)
265  continue;
266  pwrpri.replace("RECTABLE", "record");
267 
268  desc = pwrpri;
269  pwrpri += QString(" AS powerpriority ");
270 
271  tests.append(qMakePair(desc, pwrpri));
272  }
273  }
274 
275  if (recordid)
276  recmatch = QString("INNER JOIN record "
277  " ON ( record.recordid = %1 ) ")
278  .arg(recordid);
279 
280  for (Itest = tests.begin(); Itest != tests.end(); ++Itest)
281  {
282  query.prepare("SELECT " + (*Itest).second.replace("program.", "p.")
283  + QString
284  (" FROM %1 as p "
285  "INNER JOIN channel "
286  " ON ( channel.chanid = p.chanid ) "
287  "INNER JOIN capturecard "
288  " ON ( channel.sourceid = capturecard.sourceid AND "
289  " ( capturecard.schedorder <> 0 OR "
290  " capturecard.parentid = 0 ) ) ").arg(ptable)
291  + recmatch +
292  "WHERE p.chanid = :CHANID AND"
293  " p.starttime = :STARTTIME ;");
294 
295  query.bindValue(":CHANID", m_progInfo.GetChanID());
296  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
297 
298  adjustmsg = QString("%1 : ").arg((*Itest).first);
299  if (query.exec() && query.next())
300  {
301  adj = query.value(0).toInt();
302  if (adj)
303  {
304  adjustmsg += tr(" MATCHED, adding %1").arg(adj);
305  total += adj;
306  }
307  else
308  adjustmsg += tr(" not matched");
309  }
310  else
311  adjustmsg += tr(" Query FAILED");
312 
313  addItem(tr("Recording Priority Adjustment"), adjustmsg,
315  }
316 
317  if (!tests.isEmpty())
318  addItem(tr("Priority Adjustment Total"), QString::number(total),
320 }
321 
323 {
324  MSqlQuery query(MSqlQuery::InitCon());
325  QString category_type, showtype, year, syndicatedEpisodeNum;
326  QString rating, colorcode, title_pronounce;
327  float stars = 0.0;
328  int partnumber = 0, parttotal = 0;
329  int audioprop = 0, videoprop = 0, subtype = 0, generic = 0;
330  bool recorded = false;
331 
332  RecordingRule* record = nullptr;
334  {
335  record = new RecordingRule();
336  record->LoadByProgram(&m_progInfo);
337  }
338 
339  if (m_progInfo.GetFilesize())
340  recorded = true;
341 
342  QString ptable = recorded ? "recordedprogram" : "program";
343 
345  {
346  query.prepare(QString("SELECT category_type, airdate, stars,"
347  " partnumber, parttotal, audioprop+0, videoprop+0,"
348  " subtitletypes+0, syndicatedepisodenumber, generic,"
349  " showtype, colorcode, title_pronounce"
350  " FROM %1 WHERE chanid = :CHANID AND"
351  " starttime = :STARTTIME ;").arg(ptable));
352 
353  query.bindValue(":CHANID", m_progInfo.GetChanID());
354  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
355 
356  if (query.exec() && query.next())
357  {
358  category_type = query.value(0).toString();
359  year = query.value(1).toString();
360  stars = query.value(2).toFloat();
361  partnumber = query.value(3).toInt();
362  parttotal = query.value(4).toInt();
363  audioprop = query.value(5).toInt();
364  videoprop = query.value(6).toInt();
365  subtype = query.value(7).toInt();
366  syndicatedEpisodeNum = query.value(8).toString();
367  generic = query.value(9).toInt();
368  showtype = query.value(10).toString();
369  colorcode = query.value(11).toString();
370  title_pronounce = query.value(12).toString();
371  }
372  else if (!query.isActive())
373  MythDB::DBError("ProgDetails", query);
374 
375  rating = getRatings(
376  recorded, m_progInfo.GetChanID(),
378  }
379 
380  if (category_type.isEmpty() && !m_progInfo.GetProgramID().isEmpty())
381  {
382  QString prefix = m_progInfo.GetProgramID().left(2);
383 
384  if (prefix == "MV")
385  category_type = "movie";
386  else if (prefix == "EP")
387  category_type = "series";
388  else if (prefix == "SP")
389  category_type = "sports";
390  else if (prefix == "SH")
391  category_type = "tvshow";
392  }
393 
394  addItem(tr("Title"),
397 
398  addItem(tr("Title Pronounce"), title_pronounce, ProgInfoList::kLevel2);
399 
400  QString s = m_progInfo.GetDescription();
401 
402  QString attr;
403 
404  if (partnumber > 0)
405  attr += tr("Part %1 of %2, ").arg(partnumber).arg(parttotal);
406 
407  if (!rating.isEmpty() && rating != "NR")
408  attr += rating + ", ";
409  if (category_type == "movie")
410  {
411  if (!year.isEmpty())
412  attr += year + ", ";
413 
414  /* see #7810, was hardcoded to 4 star system, when every theme
415  * uses 10 stars / 5 stars with half stars
416  */
417  if (stars > 0.0F)
418  attr += tr("%n star(s)", "", roundf(stars * 10.0F)) + ", ";
419  }
420  if (!colorcode.isEmpty())
421  attr += colorcode + ", ";
422 
423  if (audioprop & AUD_MONO)
424  attr += tr("Mono") + ", ";
425  if (audioprop & AUD_STEREO)
426  attr += tr("Stereo") + ", ";
427  if (audioprop & AUD_SURROUND)
428  attr += tr("Surround Sound") + ", ";
429  if (audioprop & AUD_DOLBY)
430  attr += tr("Dolby Sound") + ", ";
431  if (audioprop & AUD_HARDHEAR)
432  attr += tr("Audio for Hearing Impaired") + ", ";
433  if (audioprop & AUD_VISUALIMPAIR)
434  attr += tr("Audio for Visually Impaired") + ", ";
435 
436  if (videoprop & VID_HDTV)
437  attr += tr("HDTV") + ", ";
438  if (videoprop & VID_WIDESCREEN)
439  attr += tr("Widescreen") + ", ";
440  if (videoprop & VID_AVC)
441  attr += tr("AVC/H.264") + ", ";
442  if (videoprop & VID_720)
443  attr += tr("720p Resolution") + ", ";
444  if (videoprop & VID_1080)
445  attr += tr("1080i/p Resolution") + ", ";
446  if (videoprop & VID_DAMAGED)
447  attr += tr("Damaged") + ", ";
448 
449  if (subtype & SUB_HARDHEAR)
450  attr += tr("CC","Closed Captioned") + ", ";
451  if (subtype & SUB_NORMAL)
452  attr += tr("Subtitles Available") + ", ";
453  if (subtype & SUB_ONSCREEN)
454  attr += tr("Subtitled") + ", ";
455  if (subtype & SUB_SIGNED)
456  attr += tr("Deaf Signing") + ", ";
457 
458  if (generic && category_type == "series")
459  attr += tr("Unidentified Episode") + ", ";
460  else if (m_progInfo.IsRepeat())
461  attr += tr("Repeat") + ", ";
462 
463  if (!attr.isEmpty())
464  {
465  attr.truncate(attr.lastIndexOf(','));
466  s += " (" + attr + ")";
467  }
468 
469  addItem(tr("Description"), s, ProgInfoList::kLevel1);
470 
471  QString actors, directors, producers, execProducers;
472  QString writers, guestStars, hosts, adapters;
473  QString presenters, commentators, guests;
474 
476  {
477  if (recorded)
478  query.prepare("SELECT role,people.name FROM recordedcredits"
479  " AS credits"
480  " LEFT JOIN people ON credits.person = people.person"
481  " WHERE credits.chanid = :CHANID"
482  " AND credits.starttime = :STARTTIME"
483  " ORDER BY role;");
484  else
485  query.prepare("SELECT role,people.name FROM credits"
486  " LEFT JOIN people ON credits.person = people.person"
487  " WHERE credits.chanid = :CHANID"
488  " AND credits.starttime = :STARTTIME"
489  " ORDER BY role;");
490  query.bindValue(":CHANID", m_progInfo.GetChanID());
491  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
492 
493  if (query.exec() && query.size() > 0)
494  {
495  QStringList plist;
496  QString rstr, role, pname;
497 
498  while(query.next())
499  {
500  role = query.value(0).toString();
501  /* The people.name column uses utf8_bin collation.
502  * Qt-MySQL drivers use QVariant::ByteArray for string-type
503  * MySQL fields marked with the BINARY attribute (those using a
504  * *_bin collation) and QVariant::String for all others.
505  * Since QVariant::toString() uses QString::fromAscii()
506  * (through QVariant::convert()) when the QVariant's type is
507  * QVariant::ByteArray, we have to use QString::fromUtf8()
508  * explicitly to prevent corrupting characters.
509  * The following code should be changed to use the simpler
510  * toString() approach, as above, if we do a DB update to
511  * coalesce the people.name values that differ only in case and
512  * change the collation to utf8_general_ci, to match the
513  * majority of other columns, or we'll have the same problem in
514  * reverse.
515  */
516  pname = QString::fromUtf8(query.value(1)
517  .toByteArray().constData());
518 
519  if (rstr != role)
520  {
521  if (rstr == "actor")
522  actors = plist.join(", ");
523  else if (rstr == "director")
524  directors = plist.join(", ");
525  else if (rstr == "producer")
526  producers = plist.join(", ");
527  else if (rstr == "executive_producer")
528  execProducers = plist.join(", ");
529  else if (rstr == "writer")
530  writers = plist.join(", ");
531  else if (rstr == "guest_star")
532  guestStars = plist.join(", ");
533  else if (rstr == "host")
534  hosts = plist.join(", ");
535  else if (rstr == "adapter")
536  adapters = plist.join(", ");
537  else if (rstr == "presenter")
538  presenters = plist.join(", ");
539  else if (rstr == "commentator")
540  commentators = plist.join(", ");
541  else if (rstr == "guest")
542  guests = plist.join(", ");
543 
544  rstr = role;
545  plist.clear();
546  }
547 
548  plist.append(pname);
549  }
550  if (rstr == "actor")
551  actors = plist.join(", ");
552  else if (rstr == "director")
553  directors = plist.join(", ");
554  else if (rstr == "producer")
555  producers = plist.join(", ");
556  else if (rstr == "executive_producer")
557  execProducers = plist.join(", ");
558  else if (rstr == "writer")
559  writers = plist.join(", ");
560  else if (rstr == "guest_star")
561  guestStars = plist.join(", ");
562  else if (rstr == "host")
563  hosts = plist.join(", ");
564  else if (rstr == "adapter")
565  adapters = plist.join(", ");
566  else if (rstr == "presenter")
567  presenters = plist.join(", ");
568  else if (rstr == "commentator")
569  commentators = plist.join(", ");
570  else if (rstr == "guest")
571  guests = plist.join(", ");
572  }
573  }
574  addItem(tr("Actors"), actors, ProgInfoList::kLevel1);
575  addItem(tr("Guest Star"), guestStars, ProgInfoList::kLevel1);
576  addItem(tr("Guest"), guests, ProgInfoList::kLevel1);
577  addItem(tr("Host"), hosts, ProgInfoList::kLevel1);
578  addItem(tr("Presenter"), presenters, ProgInfoList::kLevel1);
579  addItem(tr("Commentator"), commentators, ProgInfoList::kLevel1);
580  addItem(tr("Director"), directors, ProgInfoList::kLevel1);
581  addItem(tr("Producer"), producers, ProgInfoList::kLevel2);
582  addItem(tr("Executive Producer"), execProducers, ProgInfoList::kLevel2);
583  addItem(tr("Writer"), writers, ProgInfoList::kLevel2);
584  addItem(tr("Adapter"), adapters, ProgInfoList::kLevel2);
585 
587 
588  query.prepare("SELECT genre FROM programgenres "
589  "WHERE chanid = :CHANID AND starttime = :STARTTIME "
590  "AND relevance > 0 ORDER BY relevance;");
591  query.bindValue(":CHANID", m_progInfo.GetChanID());
592  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
593 
594  if (query.exec())
595  {
596  s.clear();
597  while (query.next())
598  {
599  if (!s.isEmpty())
600  s += ", ";
601  s += query.value(0).toString();
602  }
603  addItem(tr("Genre"), s, ProgInfoList::kLevel1);
604  }
605 
606  s.clear();
607  if (!category_type.isEmpty())
608  {
609  s = category_type;
610  if (!m_progInfo.GetSeriesID().isEmpty())
611  s += " (" + m_progInfo.GetSeriesID() + ")";
612  if (!showtype.isEmpty())
613  s += " " + showtype;
614  }
615  addItem(tr("Type", "category_type"), s, ProgInfoList::kLevel1);
616 
617  s.clear();
618  if (m_progInfo.GetSeason() > 0)
619  s = QString::number(m_progInfo.GetSeason());
620  addItem(tr("Season"), s, ProgInfoList::kLevel1);
621 
622  s.clear();
623  if (m_progInfo.GetEpisode() > 0)
624  {
625  if (m_progInfo.GetEpisodeTotal() > 0)
626  s = tr("%1 of %2").arg(m_progInfo.GetEpisode())
627  .arg(m_progInfo.GetEpisodeTotal());
628  else
629  s = QString::number(m_progInfo.GetEpisode());
630 
631  }
632  addItem(tr("Episode"), s, ProgInfoList::kLevel1);
633 
634  addItem(tr("Syndicated Episode Number"), syndicatedEpisodeNum,
636 
637  s.clear();
638  if (m_progInfo.GetOriginalAirDate().isValid() &&
639  category_type != "movie")
640  {
643  }
644  addItem(tr("Original Airdate"), s, ProgInfoList::kLevel1);
645 
647 
648  // Begin MythTV information not found in the listings info
649  QDateTime statusDate;
652  statusDate = m_progInfo.GetScheduledStartTime();
653 
654  RecordingType rectype = kSingleRecord; // avoid kNotRecording
656 
657  if (recstatus == RecStatus::PreviousRecording ||
658  recstatus == RecStatus::NeverRecord ||
659  recstatus == RecStatus::Unknown)
660  {
661  query.prepare("SELECT recstatus, starttime "
662  "FROM oldrecorded WHERE duplicate > 0 AND "
663  "future = 0 AND "
664  "((programid <> '' AND programid = :PROGRAMID) OR "
665  " (title <> '' AND title = :TITLE AND "
666  " subtitle <> '' AND subtitle = :SUBTITLE AND "
667  " description <> '' AND description = :DECRIPTION));");
668 
669  query.bindValue(":PROGRAMID", m_progInfo.GetProgramID());
670  query.bindValue(":TITLE", m_progInfo.GetTitle());
671  query.bindValue(":SUBTITLE", m_progInfo.GetSubtitle());
672  query.bindValue(":DECRIPTION", m_progInfo.GetDescription());
673 
674  if (!query.exec())
675  {
676  MythDB::DBError("showDetails", query);
677  }
678  else if (query.next())
679  {
680  if (recstatus == RecStatus::Unknown)
681  recstatus = RecStatus::Type(query.value(0).toInt());
682 
683  if (recstatus == RecStatus::PreviousRecording ||
684  recstatus == RecStatus::NeverRecord ||
685  recstatus == RecStatus::Recorded)
686  {
687  statusDate = MythDate::as_utc(query.value(1).toDateTime());
688  }
689  }
690  }
691 
692  if (recstatus == RecStatus::Unknown)
693  {
694  if (recorded)
695  {
696  recstatus = RecStatus::Recorded;
697  statusDate = m_progInfo.GetScheduledStartTime();
698  }
699  else
700  {
701  // re-enable "Not Recording" status text
702  rectype = m_progInfo.GetRecordingRuleType();
703  }
704  }
705 
706  s = RecStatus::toString(recstatus, rectype);
707 
708  if (statusDate.isValid())
709  s += " " + MythDate::toString(statusDate, MythDate::kDateFull |
711 
712  addItem(tr("MythTV Status"), s, ProgInfoList::kLevel1);
713 
714  QString recordingRule;
715  QString lastRecorded;
716  QString nextRecording;
717  QString averageTimeShift;
718  QString watchListScore;
719  QString watchListStatus;
720  QString searchPhrase;
721 
723  {
724  recordingRule = QString("%1, ").arg(m_progInfo.GetRecordingRuleID());
726  recordingRule += toString(m_progInfo.GetRecordingRuleType());
727  if (!(record->m_title.isEmpty()))
728  recordingRule += QString(" \"%2\"").arg(record->m_title);
729 
730  query.prepare("SELECT last_record, next_record, avg_delay "
731  "FROM record WHERE recordid = :RECORDID");
732  query.bindValue(":RECORDID", m_progInfo.GetRecordingRuleID());
733 
734  if (query.exec() && query.next())
735  {
736  if (query.value(0).toDateTime().isValid())
737  lastRecorded = MythDate::toString(
738  MythDate::as_utc(query.value(0).toDateTime()),
740  if (query.value(1).toDateTime().isValid())
741  nextRecording = MythDate::toString(
742  MythDate::as_utc(query.value(1).toDateTime()),
744  if (query.value(2).toInt() > 0)
745  averageTimeShift = tr("%n hour(s)", "",
746  query.value(2).toInt());
747  }
748  if (recorded)
749  {
751  watchListScore =
752  QString::number(m_progInfo.GetRecordingPriority2());
753 
755  {
757  {
758  case wlExpireOff:
759  watchListStatus = tr("Auto-expire off");
760  break;
761  case wlWatched:
762  watchListStatus = tr("Marked as 'watched'");
763  break;
764  case wlEarlier:
765  watchListStatus = tr("Not the earliest episode");
766  break;
767  case wlDeleted:
768  watchListStatus = tr("Recently deleted episode");
769  break;
770  }
771  }
772  }
773  if (record->m_searchType != kManualSearch &&
775  searchPhrase = record->m_description;
776  }
777  addItem(tr("Recording Rule"), recordingRule, ProgInfoList::kLevel1);
778  addItem(tr("Search Phrase"), searchPhrase, ProgInfoList::kLevel1);
779 
780  s.clear();
781  if (m_progInfo.GetFindID())
782  {
783  QDateTime fdate(QDate(1970, 1, 1),QTime(12,0,0));
784  fdate = fdate.addDays((int)m_progInfo.GetFindID() - 719528);
785  s = QString("%1 (%2)").arg(m_progInfo.GetFindID())
786  .arg(MythDate::toString(
788  }
789  addItem(tr("Find ID"), s, ProgInfoList::kLevel2);
790 
791  addItem(tr("Last Recorded"), lastRecorded, ProgInfoList::kLevel2);
792  addItem(tr("Next Recording"), nextRecording, ProgInfoList::kLevel2);
793  addItem(tr("Average Time Shift"), averageTimeShift, ProgInfoList::kLevel2);
794  addItem(tr("Watch List Score"), watchListScore, ProgInfoList::kLevel2);
795  addItem(tr("Watch List Status"), watchListStatus, ProgInfoList::kLevel2);
796 
797  QString recordingHost;
798  QString recordingInput;
799  QString recordedFilename;
800  QString recordedFileSize;
801  QString recordingGroup;
802  QString storageGroup;
803  QString playbackGroup;
804  QString recordingProfile;
805 
806  recordingHost = m_progInfo.GetHostname();
807  recordingInput = m_progInfo.GetInputName();
808 
809  if (recorded)
810  {
811  recordedFilename = m_progInfo.GetBasename();
812  recordedFileSize = QString("%1 ")
813  .arg(m_progInfo.GetFilesize()/((double)(1<<30)),0,'f',2);
814  recordedFileSize += tr("GB", "GigaBytes");
815 
816  query.prepare("SELECT profile FROM recorded"
817  " WHERE chanid = :CHANID"
818  " AND starttime = :STARTTIME;");
819  query.bindValue(":CHANID", m_progInfo.GetChanID());
820  query.bindValue(":STARTTIME", m_progInfo.GetRecordingStartTime());
821 
822  if (query.exec() && query.next())
823  {
824  recordingProfile = ProgramInfo::i18n(query.value(0).toString());
825  }
826  recordingGroup = ProgramInfo::i18n(m_progInfo.GetRecordingGroup());
827  storageGroup = ProgramInfo::i18n(m_progInfo.GetStorageGroup());
828  playbackGroup = ProgramInfo::i18n(m_progInfo.GetPlaybackGroup());
829  }
830  else if (m_progInfo.GetRecordingRuleID())
831  {
832  recordingProfile = record->m_recProfile;
833  }
834  addItem(tr("Recording Host"), recordingHost, ProgInfoList::kLevel2);
835  addItem(tr("Recording Input"), recordingInput, ProgInfoList::kLevel2);
836  addItem(tr("Recorded File Name"), recordedFilename, ProgInfoList::kLevel1);
837  addItem(tr("Recorded File Size"), recordedFileSize, ProgInfoList::kLevel1);
838  addItem(tr("Recording Profile"), recordingProfile, ProgInfoList::kLevel2);
839  addItem(tr("Recording Group"), recordingGroup, ProgInfoList::kLevel1);
840  addItem(tr("Storage Group"), storageGroup, ProgInfoList::kLevel2);
841  addItem(tr("Playback Group"), playbackGroup, ProgInfoList::kLevel2);
842 
843  PowerPriorities(ptable);
844 
845  delete record;
846 }
ProgInfoList m_infoList
Definition: progdetails.h:35
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:782
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:863
void PageUp(void)
Definition: proginfolist.h:34
ProgramInfo m_progInfo
Definition: progdetails.h:34
bool LoadByProgram(const ProgramInfo *proginfo)
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
virtual uint64_t GetFilesize(void) const
QString toString(MarkTypes type)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
QString GetTitle(void) const
Definition: programinfo.h:353
int size(void) const
Definition: mythdbcon.h:203
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void addItem(const QString &title, const QString &value, ProgInfoList::VisibleLevel level)
bool Create(bool focusable)
Initialise buttonlist from XML.
void Display(const DataList &data)
Build list of key:value buttons.
void updatePage(void)
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:23
void BuildFocusList(void)
void Toggle(void)
Toggle infolist state. Focusable widgets toggle between Basic & Full info. Non-focusable widgets togg...
QDate GetOriginalAirDate(void) const
Definition: programinfo.h:420
QString GetStorageGroup(void) const
Definition: programinfo.h:414
bool Create(void) override
Definition: progdetails.cpp:20
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:382
QVariant value(int i) const
Definition: mythdbcon.h:198
QString getRatings(bool recorded, uint chanid, const QDateTime &startts)
Definition: progdetails.cpp:39
def rating(profile, smoonURL, gate)
Definition: scan.py:25
void loadPage(void)
QString GetDescription(void) const
Definition: programinfo.h:357
void PowerPriorities(const QString &ptable)
QString GetBasename(void) const
Definition: programinfo.h:336
static QString toString(Type, uint id)
Converts "recstatus" into a short (unreadable) string.
Definition: recStatus.cpp:39
ProgInfoList::DataList m_data
Definition: progdetails.h:36
QString GetSubtitle(void) const
Definition: programinfo.h:355
bool isActive(void) const
Definition: mythdbcon.h:204
bool IsRepeat(void) const
Definition: programinfo.h:478
Default local time.
Definition: mythdate.h:16
QString GetRecordingGroup(void) const
Definition: programinfo.h:411
QString m_description
Definition: recordingrule.h:83
uint GetSeason(void) const
Definition: programinfo.h:358
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:32
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:389
static QString i18n(const QString &)
Translations for play,recording, & storage groups +.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:101
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
QString GetPlaybackGroup(void) const
Definition: programinfo.h:412
MythMainWindow * GetMythMainWindow(void)
QString GetSeriesID(void) const
Definition: programinfo.h:427
void PageDown(void)
Definition: proginfolist.h:33
int GetNumSetting(const QString &key, int defaultval=0)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:807
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QString m_title
Definition: recordingrule.h:79
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:439
uint GetEpisodeTotal(void) const
Definition: programinfo.h:360
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
Definition: progdetails.cpp:98
int GetRecordingPriority2(void) const
Definition: programinfo.h:433
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:443
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:364
QString m_recProfile
uint GetRecordingRuleID(void) const
Definition: programinfo.h:441
QString GetProgramID(void) const
Definition: programinfo.h:428
uint GetFindID(void) const
Definition: programinfo.h:462
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:396
bool Hide(void)
Remove infolist from display.
Add year to string if not included.
Definition: mythdate.h:22
QString GetHostname(void) const
Definition: programinfo.h:413
QString GetInputName(void) const
Definition: programinfo.h:456
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
QString GetCategory(void) const
Definition: programinfo.h:361
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
std::tuple< QString, QString, int > DataItem
Definition: proginfolist.h:20
RecSearchType m_searchType
uint GetEpisode(void) const
Definition: programinfo.h:359