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  QStringList actions;
123  bool handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
124 
125  for (int i = 0; i < actions.size() && !handled; i++)
126  {
127  QString action = actions[i];
128  handled = true;
129 
130  if (action == "INFO" || action == "SELECT")
131  {
132  m_infoList.Toggle();
133  updatePage();
134  }
135  else if (action == "DOWN")
136  {
138  }
139  else if (action == "UP")
140  {
141  m_infoList.PageUp();
142  }
143  else
144  handled = false;
145  }
146 
147  if (!handled && MythScreenType::keyPressEvent(event))
148  handled = true;
149 
150  return handled;
151 }
152 
153 void ProgDetails::PowerPriorities(const QString & ptable)
154 {
155  int recordid = m_progInfo.GetRecordingRuleID();
156 
157  // If not a scheduled recording, abort .... ?
158  if (!recordid)
159  return;
160 
161  using string_pair = QPair<QString, QString>;
162  QList<string_pair > tests;
163  QList<string_pair >::iterator Itest;
164  QString recmatch;
165  QString pwrpri;
166  QString desc;
167  QString adjustmsg;
168  int total = 0;
169 
170  MSqlQuery query(MSqlQuery::InitCon());
171 
172  int prefinputpri = gCoreContext->GetNumSetting("PrefInputPriority", 2);
173  int hdtvpriority = gCoreContext->GetNumSetting("HDTVRecPriority", 0);
174  int wspriority = gCoreContext->GetNumSetting("WSRecPriority", 0);
175  int slpriority = gCoreContext->GetNumSetting("SignLangRecPriority", 0);
176  int onscrpriority = gCoreContext->GetNumSetting("OnScrSubRecPriority", 0);
177  int ccpriority = gCoreContext->GetNumSetting("CCRecPriority", 0);
178  int hhpriority = gCoreContext->GetNumSetting("HardHearRecPriority", 0);
179  int adpriority = gCoreContext->GetNumSetting("AudioDescRecPriority", 0);
180 
181  tests.append(qMakePair(QString("channel.recpriority"),
182  QString("channel.recpriority")));
183  tests.append(qMakePair(QString("capturecard.recpriority"),
184  QString("capturecard.recpriority")));
185 
186  if (recordid && prefinputpri)
187  {
188  pwrpri = QString("(capturecard.cardid = record.prefinput) * %1")
189  .arg(prefinputpri);
190  tests.append(qMakePair(pwrpri, pwrpri));
191  }
192  if (hdtvpriority)
193  {
194  pwrpri = QString("(program.hdtv > 0 OR "
195  "FIND_IN_SET('HDTV', program.videoprop) > 0) * %1")
196  .arg(hdtvpriority);
197  tests.append(qMakePair(pwrpri, pwrpri));
198  }
199  if (wspriority)
200  {
201  pwrpri = QString
202  ("(FIND_IN_SET('WIDESCREEN', program.videoprop) > 0) * %1")
203  .arg(wspriority);
204  tests.append(qMakePair(pwrpri, pwrpri));
205  }
206  if (slpriority)
207  {
208  pwrpri = QString
209  ("(FIND_IN_SET('SIGNED', program.subtitletypes) > 0) * %1")
210  .arg(slpriority);
211  tests.append(qMakePair(pwrpri, pwrpri));
212  }
213  if (onscrpriority)
214  {
215  pwrpri = QString
216  ("(FIND_IN_SET('ONSCREEN', program.subtitletypes) > 0) * %1")
217  .arg(onscrpriority);
218  tests.append(qMakePair(pwrpri, pwrpri));
219  }
220  if (ccpriority)
221  {
222  pwrpri = QString
223  ("(FIND_IN_SET('NORMAL', program.subtitletypes) > 0 OR "
224  "program.closecaptioned > 0 OR program.subtitled > 0) * %1")
225  .arg(ccpriority);
226  tests.append(qMakePair(pwrpri, pwrpri));
227  }
228  if (hhpriority)
229  {
230  pwrpri = QString
231  ("(FIND_IN_SET('HARDHEAR', program.subtitletypes) > 0 OR "
232  "FIND_IN_SET('HARDHEAR', program.audioprop) > 0) * %1")
233  .arg(hhpriority);
234  tests.append(qMakePair(pwrpri, pwrpri));
235  }
236  if (adpriority)
237  {
238  pwrpri = QString
239  ("(FIND_IN_SET('VISUALIMPAIR', program.audioprop) > 0) * %1")
240  .arg(adpriority);
241  tests.append(qMakePair(pwrpri, pwrpri));
242  }
243 
244  query.prepare("SELECT recpriority, selectclause FROM powerpriority;");
245 
246  if (!query.exec())
247  {
248  MythDB::DBError("Power Priority", query);
249  return;
250  }
251 
252  while (query.next())
253  {
254  int adj = query.value(0).toInt();
255  if (adj)
256  {
257  QString sclause = query.value(1).toString();
258  sclause.remove(QRegExp("^\\s*AND\\s+", Qt::CaseInsensitive));
259  sclause.remove(';');
260  pwrpri = QString("(%1) * %2").arg(sclause)
261  .arg(query.value(0).toInt());
262  if (!recordid && pwrpri.indexOf("RECTABLE") != -1)
263  continue;
264  pwrpri.replace("RECTABLE", "record");
265 
266  desc = pwrpri;
267  pwrpri += QString(" AS powerpriority ");
268 
269  tests.append(qMakePair(desc, pwrpri));
270  }
271  }
272 
273  if (recordid)
274  recmatch = QString("INNER JOIN record "
275  " ON ( record.recordid = %1 ) ")
276  .arg(recordid);
277 
278  for (Itest = tests.begin(); Itest != tests.end(); ++Itest)
279  {
280  query.prepare("SELECT " + (*Itest).second.replace("program.", "p.")
281  + QString
282  (" FROM %1 as p "
283  "INNER JOIN channel "
284  " ON ( channel.chanid = p.chanid ) "
285  "INNER JOIN capturecard "
286  " ON ( channel.sourceid = capturecard.sourceid AND "
287  " ( capturecard.schedorder <> 0 OR "
288  " capturecard.parentid = 0 ) ) ").arg(ptable)
289  + recmatch +
290  "WHERE p.chanid = :CHANID AND"
291  " p.starttime = :STARTTIME ;");
292 
293  query.bindValue(":CHANID", m_progInfo.GetChanID());
294  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
295 
296  adjustmsg = QString("%1 : ").arg((*Itest).first);
297  if (query.exec() && query.next())
298  {
299  int adj = query.value(0).toInt();
300  if (adj)
301  {
302  adjustmsg += tr(" MATCHED, adding %1").arg(adj);
303  total += adj;
304  }
305  else
306  adjustmsg += tr(" not matched");
307  }
308  else
309  adjustmsg += tr(" Query FAILED");
310 
311  addItem(tr("Recording Priority Adjustment"), adjustmsg,
313  }
314 
315  if (!tests.isEmpty())
316  addItem(tr("Priority Adjustment Total"), QString::number(total),
318 }
319 
321 {
322  MSqlQuery query(MSqlQuery::InitCon());
323  QString category_type;
324  QString showtype;
325  QString year;
326  QString syndicatedEpisodeNum;
327  QString rating;
328  QString colorcode;
329  QString title_pronounce;
330  float stars = 0.0;
331  int partnumber = 0;
332  int parttotal = 0;
333  int audioprop = 0;
334  int videoprop = 0;
335  int subtype = 0;
336  int generic = 0;
337  bool recorded = false;
338 
339  RecordingRule* record = nullptr;
341  {
342  record = new RecordingRule();
343  record->LoadByProgram(&m_progInfo);
344  }
345 
346  if (m_progInfo.GetFilesize())
347  recorded = true;
348 
349  QString ptable = recorded ? "recordedprogram" : "program";
350 
352  {
353  query.prepare(QString("SELECT category_type, airdate, stars,"
354  " partnumber, parttotal, audioprop+0, videoprop+0,"
355  " subtitletypes+0, syndicatedepisodenumber, generic,"
356  " showtype, colorcode, title_pronounce"
357  " FROM %1 WHERE chanid = :CHANID AND"
358  " starttime = :STARTTIME ;").arg(ptable));
359 
360  query.bindValue(":CHANID", m_progInfo.GetChanID());
361  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
362 
363  if (query.exec() && query.next())
364  {
365  category_type = query.value(0).toString();
366  year = query.value(1).toString();
367  stars = query.value(2).toFloat();
368  partnumber = query.value(3).toInt();
369  parttotal = query.value(4).toInt();
370  audioprop = query.value(5).toInt();
371  videoprop = query.value(6).toInt();
372  subtype = query.value(7).toInt();
373  syndicatedEpisodeNum = query.value(8).toString();
374  generic = query.value(9).toInt();
375  showtype = query.value(10).toString();
376  colorcode = query.value(11).toString();
377  title_pronounce = query.value(12).toString();
378  }
379  else if (!query.isActive())
380  MythDB::DBError("ProgDetails", query);
381 
382  rating = getRatings(
383  recorded, m_progInfo.GetChanID(),
385  }
386 
387  if (category_type.isEmpty() && !m_progInfo.GetProgramID().isEmpty())
388  {
389  QString prefix = m_progInfo.GetProgramID().left(2);
390 
391  if (prefix == "MV")
392  category_type = "movie";
393  else if (prefix == "EP")
394  category_type = "series";
395  else if (prefix == "SP")
396  category_type = "sports";
397  else if (prefix == "SH")
398  category_type = "tvshow";
399  }
400 
401  addItem(tr("Title"),
404 
405  addItem(tr("Title Pronounce"), title_pronounce, ProgInfoList::kLevel2);
406 
407  QString s = m_progInfo.GetDescription();
408 
409  QString attr;
410 
411  if (partnumber > 0)
412  attr += tr("Part %1 of %2, ").arg(partnumber).arg(parttotal);
413 
414  if (!rating.isEmpty() && rating != "NR")
415  attr += rating + ", ";
416  if (category_type == "movie")
417  {
418  if (!year.isEmpty())
419  attr += year + ", ";
420 
421  /* see #7810, was hardcoded to 4 star system, when every theme
422  * uses 10 stars / 5 stars with half stars
423  */
424  if (stars > 0.0F)
425  attr += tr("%n star(s)", "", roundf(stars * 10.0F)) + ", ";
426  }
427  if (!colorcode.isEmpty())
428  attr += colorcode + ", ";
429 
430  if (audioprop & AUD_MONO)
431  attr += tr("Mono") + ", ";
432  if (audioprop & AUD_STEREO)
433  attr += tr("Stereo") + ", ";
434  if (audioprop & AUD_SURROUND)
435  attr += tr("Surround Sound") + ", ";
436  if (audioprop & AUD_DOLBY)
437  attr += tr("Dolby Sound") + ", ";
438  if (audioprop & AUD_HARDHEAR)
439  attr += tr("Audio for Hearing Impaired") + ", ";
440  if (audioprop & AUD_VISUALIMPAIR)
441  attr += tr("Audio for Visually Impaired") + ", ";
442 
443  if (videoprop & VID_HDTV)
444  attr += tr("HDTV") + ", ";
445  if (videoprop & VID_WIDESCREEN)
446  attr += tr("Widescreen") + ", ";
447  if (videoprop & VID_AVC)
448  attr += tr("AVC/H.264") + ", ";
449  if (videoprop & VID_720)
450  attr += tr("720p Resolution") + ", ";
451  if (videoprop & VID_1080)
452  attr += tr("1080i/p Resolution") + ", ";
453  if (videoprop & VID_DAMAGED)
454  attr += tr("Damaged") + ", ";
455 
456  if (subtype & SUB_HARDHEAR)
457  attr += tr("CC","Closed Captioned") + ", ";
458  if (subtype & SUB_NORMAL)
459  attr += tr("Subtitles Available") + ", ";
460  if (subtype & SUB_ONSCREEN)
461  attr += tr("Subtitled") + ", ";
462  if (subtype & SUB_SIGNED)
463  attr += tr("Deaf Signing") + ", ";
464 
465  if (generic && category_type == "series")
466  attr += tr("Unidentified Episode") + ", ";
467  else if (m_progInfo.IsRepeat())
468  attr += tr("Repeat") + ", ";
469 
470  if (!attr.isEmpty())
471  {
472  attr.truncate(attr.lastIndexOf(','));
473  s += " (" + attr + ")";
474  }
475 
476  addItem(tr("Description"), s, ProgInfoList::kLevel1);
477 
478  QString actors;
479  QString directors;
480  QString producers;
481  QString execProducers;
482  QString writers;
483  QString guestStars;
484  QString hosts;
485  QString adapters;
486  QString presenters;
487  QString commentators;
488  QString guests;
489 
491  {
492  if (recorded)
493  query.prepare("SELECT role,people.name FROM recordedcredits"
494  " AS credits"
495  " LEFT JOIN people ON credits.person = people.person"
496  " WHERE credits.chanid = :CHANID"
497  " AND credits.starttime = :STARTTIME"
498  " ORDER BY role;");
499  else
500  query.prepare("SELECT role,people.name FROM credits"
501  " LEFT JOIN people ON credits.person = people.person"
502  " WHERE credits.chanid = :CHANID"
503  " AND credits.starttime = :STARTTIME"
504  " ORDER BY role;");
505  query.bindValue(":CHANID", m_progInfo.GetChanID());
506  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
507 
508  if (query.exec() && query.size() > 0)
509  {
510  QStringList plist;
511  QString rstr;
512  QString role;
513  QString pname;
514 
515  while(query.next())
516  {
517  role = query.value(0).toString();
518  /* The people.name column uses utf8_bin collation.
519  * Qt-MySQL drivers use QVariant::ByteArray for string-type
520  * MySQL fields marked with the BINARY attribute (those using a
521  * *_bin collation) and QVariant::String for all others.
522  * Since QVariant::toString() uses QString::fromAscii()
523  * (through QVariant::convert()) when the QVariant's type is
524  * QVariant::ByteArray, we have to use QString::fromUtf8()
525  * explicitly to prevent corrupting characters.
526  * The following code should be changed to use the simpler
527  * toString() approach, as above, if we do a DB update to
528  * coalesce the people.name values that differ only in case and
529  * change the collation to utf8_general_ci, to match the
530  * majority of other columns, or we'll have the same problem in
531  * reverse.
532  */
533  pname = QString::fromUtf8(query.value(1)
534  .toByteArray().constData());
535 
536  if (rstr != role)
537  {
538  if (rstr == "actor")
539  actors = plist.join(", ");
540  else if (rstr == "director")
541  directors = plist.join(", ");
542  else if (rstr == "producer")
543  producers = plist.join(", ");
544  else if (rstr == "executive_producer")
545  execProducers = plist.join(", ");
546  else if (rstr == "writer")
547  writers = plist.join(", ");
548  else if (rstr == "guest_star")
549  guestStars = plist.join(", ");
550  else if (rstr == "host")
551  hosts = plist.join(", ");
552  else if (rstr == "adapter")
553  adapters = plist.join(", ");
554  else if (rstr == "presenter")
555  presenters = plist.join(", ");
556  else if (rstr == "commentator")
557  commentators = plist.join(", ");
558  else if (rstr == "guest")
559  guests = plist.join(", ");
560 
561  rstr = role;
562  plist.clear();
563  }
564 
565  plist.append(pname);
566  }
567  if (rstr == "actor")
568  actors = plist.join(", ");
569  else if (rstr == "director")
570  directors = plist.join(", ");
571  else if (rstr == "producer")
572  producers = plist.join(", ");
573  else if (rstr == "executive_producer")
574  execProducers = plist.join(", ");
575  else if (rstr == "writer")
576  writers = plist.join(", ");
577  else if (rstr == "guest_star")
578  guestStars = plist.join(", ");
579  else if (rstr == "host")
580  hosts = plist.join(", ");
581  else if (rstr == "adapter")
582  adapters = plist.join(", ");
583  else if (rstr == "presenter")
584  presenters = plist.join(", ");
585  else if (rstr == "commentator")
586  commentators = plist.join(", ");
587  else if (rstr == "guest")
588  guests = plist.join(", ");
589  }
590  }
591  addItem(tr("Actors"), actors, ProgInfoList::kLevel1);
592  addItem(tr("Guest Star"), guestStars, ProgInfoList::kLevel1);
593  addItem(tr("Guest"), guests, ProgInfoList::kLevel1);
594  addItem(tr("Host"), hosts, ProgInfoList::kLevel1);
595  addItem(tr("Presenter"), presenters, ProgInfoList::kLevel1);
596  addItem(tr("Commentator"), commentators, ProgInfoList::kLevel1);
597  addItem(tr("Director"), directors, ProgInfoList::kLevel1);
598  addItem(tr("Producer"), producers, ProgInfoList::kLevel2);
599  addItem(tr("Executive Producer"), execProducers, ProgInfoList::kLevel2);
600  addItem(tr("Writer"), writers, ProgInfoList::kLevel2);
601  addItem(tr("Adapter"), adapters, ProgInfoList::kLevel2);
602 
604 
605  query.prepare("SELECT genre FROM programgenres "
606  "WHERE chanid = :CHANID AND starttime = :STARTTIME "
607  "AND relevance > 0 ORDER BY relevance;");
608  query.bindValue(":CHANID", m_progInfo.GetChanID());
609  query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime());
610 
611  if (query.exec())
612  {
613  s.clear();
614  while (query.next())
615  {
616  if (!s.isEmpty())
617  s += ", ";
618  s += query.value(0).toString();
619  }
620  addItem(tr("Genre"), s, ProgInfoList::kLevel1);
621  }
622 
623  s.clear();
624  if (!category_type.isEmpty())
625  {
626  s = category_type;
627  if (!m_progInfo.GetSeriesID().isEmpty())
628  s += " (" + m_progInfo.GetSeriesID() + ")";
629  if (!showtype.isEmpty())
630  s += " " + showtype;
631  }
632  addItem(tr("Type", "category_type"), s, ProgInfoList::kLevel1);
633 
634  s.clear();
635  if (m_progInfo.GetSeason() > 0)
636  s = QString::number(m_progInfo.GetSeason());
637  addItem(tr("Season"), s, ProgInfoList::kLevel1);
638 
639  s.clear();
640  if (m_progInfo.GetEpisode() > 0)
641  {
642  if (m_progInfo.GetEpisodeTotal() > 0)
643  s = tr("%1 of %2").arg(m_progInfo.GetEpisode())
644  .arg(m_progInfo.GetEpisodeTotal());
645  else
646  s = QString::number(m_progInfo.GetEpisode());
647 
648  }
649  addItem(tr("Episode"), s, ProgInfoList::kLevel1);
650 
651  addItem(tr("Syndicated Episode Number"), syndicatedEpisodeNum,
653 
654  s.clear();
655  if (m_progInfo.GetOriginalAirDate().isValid() &&
656  category_type != "movie")
657  {
660  }
661  addItem(tr("Original Airdate"), s, ProgInfoList::kLevel1);
662 
664 
665  // Begin MythTV information not found in the listings info
666  QDateTime statusDate;
669  statusDate = m_progInfo.GetScheduledStartTime();
670 
671  RecordingType rectype = kSingleRecord; // avoid kNotRecording
673 
674  if (recstatus == RecStatus::PreviousRecording ||
675  recstatus == RecStatus::NeverRecord ||
676  recstatus == RecStatus::Unknown)
677  {
678  query.prepare("SELECT recstatus, starttime "
679  "FROM oldrecorded WHERE duplicate > 0 AND "
680  "future = 0 AND "
681  "((programid <> '' AND programid = :PROGRAMID) OR "
682  " (title <> '' AND title = :TITLE AND "
683  " subtitle <> '' AND subtitle = :SUBTITLE AND "
684  " description <> '' AND description = :DECRIPTION));");
685 
686  query.bindValue(":PROGRAMID", m_progInfo.GetProgramID());
687  query.bindValue(":TITLE", m_progInfo.GetTitle());
688  query.bindValue(":SUBTITLE", m_progInfo.GetSubtitle());
689  query.bindValue(":DECRIPTION", m_progInfo.GetDescription());
690 
691  if (!query.exec())
692  {
693  MythDB::DBError("showDetails", query);
694  }
695  else if (query.next())
696  {
697  if (recstatus == RecStatus::Unknown)
698  recstatus = RecStatus::Type(query.value(0).toInt());
699 
700  if (recstatus == RecStatus::PreviousRecording ||
701  recstatus == RecStatus::NeverRecord ||
702  recstatus == RecStatus::Recorded)
703  {
704  statusDate = MythDate::as_utc(query.value(1).toDateTime());
705  }
706  }
707  }
708 
709  if (recstatus == RecStatus::Unknown)
710  {
711  if (recorded)
712  {
713  recstatus = RecStatus::Recorded;
714  statusDate = m_progInfo.GetScheduledStartTime();
715  }
716  else
717  {
718  // re-enable "Not Recording" status text
719  rectype = m_progInfo.GetRecordingRuleType();
720  }
721  }
722 
723  s = RecStatus::toString(recstatus, rectype);
724 
725  if (statusDate.isValid())
726  s += " " + MythDate::toString(statusDate, MythDate::kDateFull |
728 
729  addItem(tr("MythTV Status"), s, ProgInfoList::kLevel1);
730 
731  QString recordingRule;
732  QString lastRecorded;
733  QString nextRecording;
734  QString averageTimeShift;
735  QString watchListScore;
736  QString watchListStatus;
737  QString searchPhrase;
738 
740  {
741  recordingRule = QString("%1, ").arg(m_progInfo.GetRecordingRuleID());
743  recordingRule += toString(m_progInfo.GetRecordingRuleType());
744  if (!(record->m_title.isEmpty()))
745  recordingRule += QString(" \"%2\"").arg(record->m_title);
746 
747  query.prepare("SELECT last_record, next_record, avg_delay "
748  "FROM record WHERE recordid = :RECORDID");
749  query.bindValue(":RECORDID", m_progInfo.GetRecordingRuleID());
750 
751  if (query.exec() && query.next())
752  {
753  if (query.value(0).toDateTime().isValid())
754  lastRecorded = MythDate::toString(
755  MythDate::as_utc(query.value(0).toDateTime()),
757  if (query.value(1).toDateTime().isValid())
758  nextRecording = MythDate::toString(
759  MythDate::as_utc(query.value(1).toDateTime()),
761  if (query.value(2).toInt() > 0)
762  averageTimeShift = tr("%n hour(s)", "",
763  query.value(2).toInt());
764  }
765  if (recorded)
766  {
768  watchListScore =
769  QString::number(m_progInfo.GetRecordingPriority2());
770 
772  {
774  {
775  case wlExpireOff:
776  watchListStatus = tr("Auto-expire off");
777  break;
778  case wlWatched:
779  watchListStatus = tr("Marked as 'watched'");
780  break;
781  case wlEarlier:
782  watchListStatus = tr("Not the earliest episode");
783  break;
784  case wlDeleted:
785  watchListStatus = tr("Recently deleted episode");
786  break;
787  }
788  }
789  }
790  if (record->m_searchType != kManualSearch &&
792  searchPhrase = record->m_description;
793  }
794  addItem(tr("Recording Rule"), recordingRule, ProgInfoList::kLevel1);
795  addItem(tr("Search Phrase"), searchPhrase, ProgInfoList::kLevel1);
796 
797  s.clear();
798  if (m_progInfo.GetFindID())
799  {
800  QDateTime fdate(QDate(1970, 1, 1),QTime(12,0,0));
801  fdate = fdate.addDays((int)m_progInfo.GetFindID() - 719528);
802  s = QString("%1 (%2)").arg(m_progInfo.GetFindID())
803  .arg(MythDate::toString(
805  }
806  addItem(tr("Find ID"), s, ProgInfoList::kLevel2);
807 
808  addItem(tr("Last Recorded"), lastRecorded, ProgInfoList::kLevel2);
809  addItem(tr("Next Recording"), nextRecording, ProgInfoList::kLevel2);
810  addItem(tr("Average Time Shift"), averageTimeShift, ProgInfoList::kLevel2);
811  addItem(tr("Watch List Score"), watchListScore, ProgInfoList::kLevel2);
812  addItem(tr("Watch List Status"), watchListStatus, ProgInfoList::kLevel2);
813 
814  QString recordingHost;
815  QString recordingInput;
816  QString recordedFilename;
817  QString recordedFileSize;
818  QString recordingGroup;
819  QString storageGroup;
820  QString playbackGroup;
821  QString recordingProfile;
822 
823  recordingHost = m_progInfo.GetHostname();
824  recordingInput = m_progInfo.GetInputName();
825 
826  if (recorded)
827  {
828  recordedFilename = m_progInfo.GetBasename();
829  recordedFileSize = QString("%1 ")
830  .arg(m_progInfo.GetFilesize()/((double)(1<<30)),0,'f',2);
831  recordedFileSize += tr("GB", "GigaBytes");
832 
833  query.prepare("SELECT profile FROM recorded"
834  " WHERE chanid = :CHANID"
835  " AND starttime = :STARTTIME;");
836  query.bindValue(":CHANID", m_progInfo.GetChanID());
837  query.bindValue(":STARTTIME", m_progInfo.GetRecordingStartTime());
838 
839  if (query.exec() && query.next())
840  {
841  recordingProfile = ProgramInfo::i18n(query.value(0).toString());
842  }
843  recordingGroup = ProgramInfo::i18n(m_progInfo.GetRecordingGroup());
844  storageGroup = ProgramInfo::i18n(m_progInfo.GetStorageGroup());
845  playbackGroup = ProgramInfo::i18n(m_progInfo.GetPlaybackGroup());
846  }
847  else if (m_progInfo.GetRecordingRuleID())
848  {
849  recordingProfile = record ? record->m_recProfile : tr("Unknown");
850  }
851  addItem(tr("Recording Host"), recordingHost, ProgInfoList::kLevel2);
852  addItem(tr("Recording Input"), recordingInput, ProgInfoList::kLevel2);
853  addItem(tr("Recorded File Name"), recordedFilename, ProgInfoList::kLevel1);
854  addItem(tr("Recorded File Size"), recordedFileSize, ProgInfoList::kLevel1);
855  addItem(tr("Recording Profile"), recordingProfile, ProgInfoList::kLevel2);
856  addItem(tr("Recording Group"), recordingGroup, ProgInfoList::kLevel1);
857  addItem(tr("Storage Group"), storageGroup, ProgInfoList::kLevel2);
858  addItem(tr("Playback Group"), playbackGroup, ProgInfoList::kLevel2);
859 
860  PowerPriorities(ptable);
861 
862  delete record;
863 }
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
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
static QString getRatings(bool recorded, uint chanid, const QDateTime &startts)
Definition: progdetails.cpp:39
def rating(profile, smoonURL, gate)
Definition: scan.py:39
void loadPage(void)
QString GetDescription(void) const
Definition: programinfo.h:357
void PowerPriorities(const QString &ptable)
QString GetBasename(void) const
Definition: programinfo.h:336
Default local time.
Definition: mythdate.h:16
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
QString GetRecordingGroup(void) const
Definition: programinfo.h:411
QString m_description
Definition: recordingrule.h:83
Add year to string if not included.
Definition: mythdate.h:22
uint GetSeason(void) const
Definition: programinfo.h:358
unsigned int uint
Definition: compat.h:140
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.
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