MythTV  master
recordingrule.cpp
Go to the documentation of this file.
1 
2 #include "recordingrule.h"
3 
4 #include <utility>
5 
6 #include <QTimeZone>
7 
8 // libmythbase
10 #include "libmythbase/mythdate.h"
11 #include "libmythbase/mythdb.h"
13 
14 // libmythtv
15 #include "scheduledrecording.h" // For RescheduleMatch()
16 #include "playgroup.h" // For GetInitialName()
17 #include "recordingprofile.h" // For constants
18 
19 static inline QString null_to_empty(const QString &str)
20 {
21  return str.isEmpty() ? "" : str;
22 }
23 
24 // If the GetNumSetting() calls here are ever removed, update schema
25 // upgrade 1302 in dbcheck.cpp to manually apply them to the Default
26 // template. Failing to do so will cause users upgrading from older
27 // versions to lose those settings.
28 
30  : m_findtime(QTime::fromString("00:00:00", Qt::ISODate)),
31  m_findid(QDate(1970, 1, 1).daysTo(MythDate::current().toLocalTime().date())
32  + 719528),
33  m_transcoder(RecordingProfile::kTranscoderAutodetect)
34 {
35  QDateTime dt = MythDate::current();
36  m_enddate = m_startdate = dt.date();
37  m_endtime = m_starttime = dt.time();
38 
40 }
41 
46 {
47  std::shared_ptr<MythSortHelper>sh = getMythSortHelper();
48 
49  if (m_sortTitle.isEmpty() and not m_title.isEmpty())
51  if (m_sortSubtitle.isEmpty() and not m_subtitle.isEmpty())
53 }
54 
58 bool RecordingRule::Load(bool asTemplate)
59 {
60  if (m_recordID <= 0)
61  return false;
62 
64  query.prepare("SELECT type, search, " // 00-01
65  "recpriority, prefinput, startoffset, endoffset, dupmethod, dupin, " // 02-07
66  "inactive, profile, recgroup, storagegroup, playgroup, autoexpire, " // 08-13
67  "maxepisodes, maxnewest, autocommflag, autotranscode, transcoder, " // 14-18
68  "autouserjob1, autouserjob2, autouserjob3, autouserjob4, " // 19-22
69  "autometadata, parentid, title, subtitle, description, season, episode, " // 23-29
70  "category, starttime, startdate, endtime, enddate, seriesid, programid, " // 30-36
71  "inetref, chanid, station, findday, findtime, findid, " // 37-42
72  "next_record, last_record, last_delete, avg_delay, filter, recgroupid, " // 43-48
73  "autoextend " // 49
74  "FROM record WHERE recordid = :RECORDID ;");
75 
76  query.bindValue(":RECORDID", m_recordID);
77 
78  if (!query.exec())
79  {
80  MythDB::DBError("SELECT record", query);
81  return false;
82  }
83 
84  if (!query.next())
85  return false;
86 
87  // Schedule
88  if (!asTemplate)
89  {
90  m_type = static_cast<RecordingType>(query.value(0).toInt());
91  m_searchType = static_cast<RecSearchType>(query.value(1).toInt());
92  }
93  m_recPriority = query.value(2).toInt();
94  m_prefInput = query.value(3).toInt();
95  m_startOffset = query.value(4).toInt();
96  m_endOffset = query.value(5).toInt();
97  m_dupMethod = static_cast<RecordingDupMethodType>
98  (query.value(6).toInt());
99  m_dupIn = static_cast<RecordingDupInType>(query.value(7).toInt());
100  m_filter = query.value(47).toUInt();
101  m_isInactive = query.value(8).toBool();
102  m_autoExtend = static_cast<AutoExtendType>(query.value(49).toUInt());
103 
104  // Storage
105  m_recProfile = query.value(9).toString();
106  m_recGroupID = query.value(48).toUInt();
107  m_storageGroup = query.value(11).toString();
108  m_playGroup = query.value(12).toString();
109  m_autoExpire = query.value(13).toBool();
110  m_maxEpisodes = query.value(14).toInt();
111  m_maxNewest = query.value(15).toBool();
112 
113  // Post Process
114  m_autoCommFlag = query.value(16).toBool();
115  m_autoTranscode = query.value(17).toBool();
116  m_transcoder = query.value(18).toInt();
117  m_autoUserJob1 = query.value(19).toBool();
118  m_autoUserJob2 = query.value(20).toBool();
119  m_autoUserJob3 = query.value(21).toBool();
120  m_autoUserJob4 = query.value(22).toBool();
121  m_autoMetadataLookup = query.value(23).toBool();
122 
123  if (!asTemplate)
124  {
125  // Original rule id for override rule
126  m_parentRecID = query.value(24).toInt();
127 
128  // Recording metadata
129  m_title = query.value(25).toString();
130  m_subtitle = query.value(26).toString();
131  m_description = query.value(27).toString();
132  m_season = query.value(28).toUInt();
133  m_episode = query.value(29).toUInt();
134  m_category = query.value(30).toString();
135  m_starttime = query.value(31).toTime();
136  m_startdate = query.value(32).toDate();
137  m_endtime = query.value(33).toTime();
138  m_enddate = query.value(34).toDate();
139  m_seriesid = query.value(35).toString();
140  m_programid = query.value(36).toString();
141  m_inetref = query.value(37).toString();
142 
143  // Associated data for rule types
144  m_channelid = query.value(38).toInt();
145  m_station = query.value(39).toString();
146  m_findday = query.value(40).toInt();
147  m_findtime = query.value(41).toTime();
148  m_findid = query.value(42).toInt();
149 
150  // Statistic fields - Used to generate statistics about particular rules
151  // and influence watch list weighting
152  m_nextRecording = MythDate::as_utc(query.value(43).toDateTime());
153  m_lastRecorded = MythDate::as_utc(query.value(44).toDateTime());
154  m_lastDeleted = MythDate::as_utc(query.value(45).toDateTime());
155  m_averageDelay = query.value(46).toInt();
156  }
157 
160  m_template = (asTemplate || m_isTemplate) ?
161  query.value(30).toString() : "";
162 
163  if (!asTemplate)
164  m_loaded = true;
165 
167  return true;
168 }
169 
171 {
172  if (!proginfo)
173  return false;
174 
175  m_progInfo = proginfo;
176 
177  m_recordID = proginfo->GetRecordingRuleID();
178  if (m_recordID)
179  {
180  if (!Load())
181  return false;
182  }
183  else
184  {
185  LoadTemplate(proginfo->GetTitle(), proginfo->GetCategory(),
186  proginfo->GetCategoryTypeString());
187  }
188 
189  if (m_type != kTemplateRecord &&
191  {
193  if (!proginfo->GetRecordingRuleID())
195  }
196 
198  m_loaded = true;
199  return true;
200 }
201 
218 bool RecordingRule::LoadBySearch(RecSearchType lsearch, const QString& textname,
219  const QString& forwhat, QString joininfo,
220  ProgramInfo *pginfo)
221 {
222  MSqlQuery query(MSqlQuery::InitCon());
223 
224  int rid = 0;
225  query.prepare("SELECT recordid FROM record WHERE "
226  "search = :SEARCH AND description LIKE :FORWHAT");
227  query.bindValue(":SEARCH", lsearch);
228  query.bindValue(":FORWHAT", forwhat);
229 
230  if (query.exec())
231  {
232  if (query.next())
233  rid = query.value(0).toInt();
234  // else rid is zero, which is valid, we're looking at a new rule
235  }
236  else
237  {
238  MythDB::DBError("loadBySearch", query);
239  return false;
240  }
241 
242  if (rid)
243  {
244  m_recordID = rid;
245  if (!Load())
246  return false;
247  }
248  else
249  {
250  LoadTemplate("Default");
251 
252  QString searchType;
253  m_searchType = lsearch;
254  searchType = SearchTypeToString(m_searchType);
255 
256  QString ltitle = QString("%1 (%2)").arg(textname, searchType);
257  m_title = ltitle;
258  m_sortTitle = nullptr;
259  m_subtitle = m_sortSubtitle = std::move(joininfo);
260  m_description = forwhat;
261 
262  if (pginfo)
263  {
264  m_findday =
265  (pginfo->GetScheduledStartTime().toLocalTime().date()
266  .dayOfWeek() + 1) % 7;
267  m_findtime = pginfo->GetScheduledStartTime().toLocalTime().time();
268  m_findid = QDate(1970, 1, 1).daysTo(
269  pginfo->GetScheduledStartTime().toLocalTime().date()) + 719528;
270  }
271  }
272 
274  m_loaded = true;
275  return true;
276 }
277 
278 bool RecordingRule::LoadTemplate(const QString& title,
279  const QString& category,
280  const QString& categoryType)
281 {
282  QString lcategory = category.isEmpty() ? "Default" : category;
283  QString lcategoryType = categoryType.isEmpty() ? "Default" : categoryType;
284 
285  MSqlQuery query(MSqlQuery::InitCon());
286  query.prepare("SELECT recordid, category, "
287  " (category = :TITLE1) AS titlematch, "
288  " (category = :CAT1) AS catmatch, "
289  " (category = :CATTYPE1) AS typematch "
290  "FROM record "
291  "WHERE type = :TEMPLATE AND "
292  " (category IN (:TITLE2, :CAT2, :CATTYPE2) "
293  " OR category = 'Default') "
294  "ORDER BY titlematch DESC, catmatch DESC, typematch DESC"
295  );
296  query.bindValue(":TEMPLATE", kTemplateRecord);
297  query.bindValue(":TITLE1", title);
298  query.bindValue(":TITLE2", title);
299  query.bindValue(":CAT1", lcategory);
300  query.bindValue(":CAT2", lcategory);
301  query.bindValue(":CATTYPE1", lcategoryType);
302  query.bindValue(":CATTYPE2", lcategoryType);
303 
304  if (!query.exec())
305  {
306  MythDB::DBError("LoadByTemplate", query);
307  return false;
308  }
309 
310  if (!query.next())
311  return false;
312 
313  int savedRecordID = m_recordID;
314  m_recordID = query.value(0).toInt();
315  bool result = Load(true);
316  m_recordID = savedRecordID;
317 
318  return result;
319 }
320 
321 bool RecordingRule::MakeTemplate(QString category)
322 {
323  if (m_recordID > 0)
324  return false;
325 
326  if (category.compare(tr("Default"), Qt::CaseInsensitive) == 0)
327  {
328  category = "Default";
329  m_title = tr("Default (Template)");
331  }
332  else
333  {
334  //: %1 is the category
335  m_title = tr("%1 (Template)").arg(category);
337  }
338 
339  LoadTemplate(category);
340  m_recordID = 0;
342  m_category = category;
343  m_loaded = true;
344  m_isTemplate = true;
345 
346  return true;
347 }
348 
349 bool RecordingRule::ModifyPowerSearchByID(int rid, const QString& textname,
350  QString forwhat, QString joininfo)
351 {
352  if (rid <= 0)
353  return false;
354 
355  m_recordID = rid;
356  if (!Load() || m_searchType != kPowerSearch)
357  return false;
358 
359  QString ltitle = QString("%1 (%2)").arg(textname, tr("Power Search"));
360  m_title = ltitle;
361  m_sortTitle = nullptr;
362  m_subtitle = m_sortSubtitle = std::move(joininfo);
363  m_description = std::move(forwhat);
364 
366  m_loaded = true;
367  return true;
368 }
369 
371 {
372  if (m_recordID <= 0)
373  return false;
374 
376  return false;
377 
378  m_isOverride = true;
380  m_recordID = 0;
382  m_isInactive = false;
383 
386 
388 
389  return true;
390 }
391 
392 bool RecordingRule::Save(bool sendSig)
393 {
394  QString sql = "SET type = :TYPE, search = :SEARCHTYPE, "
395  "recpriority = :RECPRIORITY, prefinput = :INPUT, "
396  "startoffset = :STARTOFFSET, endoffset = :ENDOFFSET, "
397  "dupmethod = :DUPMETHOD, dupin = :DUPIN, "
398  "filter = :FILTER, autoextend = :AUTOEXTEND, "
399  "inactive = :INACTIVE, profile = :RECPROFILE, "
400  "recgroup = :RECGROUP, "
401  "recgroupid = :RECGROUPID, "
402  "storagegroup = :STORAGEGROUP, "
403  "playgroup = :PLAYGROUP, autoexpire = :AUTOEXPIRE, "
404  "maxepisodes = :MAXEPISODES, maxnewest = :MAXNEWEST, "
405  "autocommflag = :AUTOCOMMFLAG, "
406  "autotranscode = :AUTOTRANSCODE, "
407  "transcoder = :TRANSCODER, autouserjob1 = :AUTOUSERJOB1, "
408  "autouserjob2 = :AUTOUSERJOB2, "
409  "autouserjob3 = :AUTOUSERJOB3, "
410  "autouserjob4 = :AUTOUSERJOB4, "
411  "autometadata = :AUTOMETADATA, "
412  "parentid = :PARENTID, title = :TITLE, "
413  "subtitle = :SUBTITLE, season = :SEASON, episode = :EPISODE, "
414  "description = :DESCRIPTION, category = :CATEGORY, "
415  "starttime = :STARTTIME, startdate = :STARTDATE, "
416  "endtime = :ENDTIME, enddate = :ENDDATE, seriesid = :SERIESID, "
417  "programid = :PROGRAMID, inetref = :INETREF, chanid = :CHANID, "
418  "station = :STATION, findday = :FINDDAY, "
419  "findtime = :FINDTIME, findid = :FINDID, "
420  "next_record = :NEXTREC, last_record = :LASTREC, "
421  "last_delete = :LASTDELETE, avg_delay = :AVGDELAY ";
422 
423  QString sqlquery;
424  if (m_recordID > 0 || (m_recordTable != "record" && m_tempID > 0))
425  {
426  sqlquery = QString("UPDATE %1 %2 WHERE recordid = :RECORDID;")
427  .arg(m_recordTable, sql);
428  }
429  else
430  {
431  sqlquery = QString("INSERT INTO %1 %2;").arg(m_recordTable, sql);
432  }
433 
434  MSqlQuery query(MSqlQuery::InitCon());
435  query.prepare(sqlquery);
436  query.bindValue(":TYPE", m_type);
437  query.bindValue(":SEARCHTYPE", m_searchType);
438  query.bindValue(":RECPRIORITY", m_recPriority);
439  query.bindValue(":INPUT", m_prefInput);
440  query.bindValue(":STARTOFFSET", m_startOffset);
441  query.bindValue(":ENDOFFSET", m_endOffset);
442  query.bindValue(":DUPMETHOD", m_dupMethod);
443  query.bindValue(":DUPIN", m_dupIn);
444  query.bindValue(":FILTER", m_filter);
445  query.bindValue(":AUTOEXTEND", static_cast<int>(m_autoExtend));
446  query.bindValue(":INACTIVE", m_isInactive);
447  query.bindValue(":RECPROFILE", null_to_empty(m_recProfile));
448  // Temporary, remove once transition to recgroupid is complete
450  query.bindValue(":RECGROUPID", m_recGroupID);
451  query.bindValue(":STORAGEGROUP", null_to_empty(m_storageGroup));
452  query.bindValue(":PLAYGROUP", null_to_empty(m_playGroup));
453  query.bindValue(":AUTOEXPIRE", m_autoExpire);
454  query.bindValue(":MAXEPISODES", m_maxEpisodes);
455  query.bindValue(":MAXNEWEST", m_maxNewest);
456  query.bindValue(":AUTOCOMMFLAG", m_autoCommFlag);
457  query.bindValue(":AUTOTRANSCODE", m_autoTranscode);
458  query.bindValue(":TRANSCODER", m_transcoder);
459  query.bindValue(":AUTOUSERJOB1", m_autoUserJob1);
460  query.bindValue(":AUTOUSERJOB2", m_autoUserJob2);
461  query.bindValue(":AUTOUSERJOB3", m_autoUserJob3);
462  query.bindValue(":AUTOUSERJOB4", m_autoUserJob4);
463  query.bindValue(":AUTOMETADATA", m_autoMetadataLookup);
464  query.bindValue(":PARENTID", m_parentRecID);
465  query.bindValue(":TITLE", m_title);
466  query.bindValue(":SUBTITLE", null_to_empty(m_subtitle));
467  query.bindValue(":DESCRIPTION", null_to_empty(m_description));
468  query.bindValue(":SEASON", m_season);
469  query.bindValue(":EPISODE", m_episode);
470  query.bindValue(":CATEGORY", null_to_empty(m_category));
471  query.bindValue(":STARTTIME", m_starttime);
472  query.bindValue(":STARTDATE", m_startdate);
473  query.bindValue(":ENDTIME", m_endtime);
474  query.bindValue(":ENDDATE", m_enddate);
475  query.bindValue(":SERIESID", null_to_empty(m_seriesid));
476  query.bindValue(":PROGRAMID", null_to_empty(m_programid));
477  query.bindValue(":INETREF", null_to_empty(m_inetref));
478  query.bindValue(":CHANID", m_channelid);
479  query.bindValue(":STATION", null_to_empty(m_station));
480  query.bindValue(":FINDDAY", m_findday);
481  query.bindValue(":FINDTIME", m_findtime);
482  query.bindValue(":FINDID", m_findid);
483  query.bindValue(":NEXTREC", m_nextRecording);
484  query.bindValue(":LASTREC", m_lastRecorded);
485  query.bindValue(":LASTDELETE", m_lastDeleted);
486  query.bindValue(":AVGDELAY", m_averageDelay);
487 
488  if (m_recordTable != "record" && m_tempID > 0)
489  query.bindValue(":RECORDID", m_tempID);
490  else if (m_recordID > 0)
491  query.bindValue(":RECORDID", m_recordID);
492 
493  if (!query.exec())
494  {
495  MythDB::DBError("UPDATE/INSERT record", query);
496  return false;
497  }
498 
499  if (m_recordTable != "record" && m_tempID <= 0)
500  m_tempID = query.lastInsertId().toInt();
501  else if (m_recordID <= 0)
502  m_recordID = query.lastInsertId().toInt();
503 
504  if (sendSig)
506  QString("SaveRule %1").arg(m_title));
507 
508  return true;
509 }
510 
511 bool RecordingRule::Delete(bool sendSig)
512 {
513  if (m_recordID < 0)
514  return false;
515 
516  MSqlQuery query(MSqlQuery::InitCon());
517  query.prepare("DELETE FROM record WHERE recordid = :RECORDID");
518  query.bindValue(":RECORDID", m_recordID);
519  if (!query.exec())
520  {
521  MythDB::DBError("ScheduledRecording::remove -- record", query);
522  return false;
523  }
524 
525  query.prepare("DELETE FROM oldfind WHERE recordid = :RECORDID");
526  query.bindValue(":RECORDID", m_recordID);
527  if (!query.exec())
528  {
529  MythDB::DBError("ScheduledRecording::remove -- oldfind", query);
530  }
531 
533  {
534  query.prepare("DELETE FROM program WHERE manualid = :RECORDID");
535  query.bindValue(":RECORDID", m_recordID);
536  if (!query.exec())
537  {
538  MythDB::DBError("ScheduledRecording::remove -- oldfind", query);
539  }
540  }
541 
542  if (sendSig)
544  QString("DeleteRule %1").arg(m_title));
545 
546  // Set m_recordID to zero, the rule is no longer in the database so it's
547  // not valid. Should you want, this allows a rule to be removed from the
548  // database and then re-inserted with Save()
549  m_recordID = 0;
550 
551  return true;
552 }
553 
554 void RecordingRule::ToMap(InfoMap &infoMap, uint date_format) const
555 {
556  if (m_title == "Default (Template)")
557  {
558  infoMap["title"] = tr("Default (Template)");
559  infoMap["sorttitle"] = tr("Default (Template)");
560  }
561  else
562  {
563  infoMap["title"] = m_title;
564  infoMap["sorttitle"] = m_sortTitle;
565  }
566  infoMap["subtitle"] = m_subtitle;
567  infoMap["sortsubtitle"] = m_sortSubtitle;
568  infoMap["description"] = m_description;
569  infoMap["season"] = QString::number(m_season);
570  infoMap["episode"] = QString::number(m_episode);
571 
572  if (m_category == "Default")
573  infoMap["category"] = tr("Default", "category");
574  else
575  infoMap["category"] = m_category;
576  infoMap["callsign"] = m_station;
577 
578 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
579  QDateTime starttm(m_startdate, m_starttime, Qt::UTC);
580 #else
581  QDateTime starttm(m_startdate, m_starttime, QTimeZone(QTimeZone::UTC));
582 #endif
583  infoMap["starttime"] = MythDate::toString(starttm, date_format | MythDate::kTime);
584  infoMap["startdate"] = MythDate::toString(
585  starttm, date_format | MythDate::kDateFull | MythDate::kSimplify);
586 
587 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
588  QDateTime endtm(m_enddate, m_endtime, Qt::UTC);
589 #else
590  QDateTime endtm(m_enddate, m_endtime, QTimeZone(QTimeZone::UTC));
591 #endif
592  infoMap["endtime"] = MythDate::toString(endtm, date_format | MythDate::kTime);
593  infoMap["enddate"] = MythDate::toString(
594  endtm, date_format | MythDate::kDateFull | MythDate::kSimplify);
595 
596  infoMap["inetref"] = m_inetref;
597  infoMap["chanid"] = QString::number(m_channelid);
598  infoMap["channel"] = m_station;
599 
600 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
601  QDateTime startts(m_startdate, m_starttime, Qt::UTC);
602  QDateTime endts(m_enddate, m_endtime, Qt::UTC);
603 #else
604  static const QTimeZone utc(QTimeZone::UTC);
605  QDateTime startts(m_startdate, m_starttime, utc);
606  QDateTime endts(m_enddate, m_endtime, utc);
607 #endif
608 
609  int seconds = startts.secsTo(endts);
610  int minutes = seconds / 60;
611  int hours = minutes / 60;
612  minutes = minutes % 60;
613 
614  infoMap["lenmins"] = QCoreApplication::translate("(Common)", "%n minute(s)",
615  "", minutes);
616 
617  QString minstring = QCoreApplication::translate("(Common)", "%n minute(s)",
618  "", minutes);
619 
620  QString hourstring = QCoreApplication::translate("(Common)", "%n hour(s)",
621  "", hours);
622 
623  if (hours > 0)
624  {
625  //: Time duration, %1 is replaced by the hours, %2 by the minutes
626  infoMap["lentime"] = QCoreApplication::translate("(Common)", "%1 %2",
627  "Hours and minutes").arg(hourstring, minstring);
628  }
629  else
630  {
631  infoMap["lentime"] = minstring;
632  }
633 
634 
635  infoMap["timedate"] = MythDate::toString(
636  startts, date_format | MythDate::kDateTimeFull | MythDate::kSimplify) + " - " +
637  MythDate::toString(endts, date_format | MythDate::kTime);
638 
639  infoMap["shorttimedate"] =
641  startts, date_format | MythDate::kDateTimeShort | MythDate::kSimplify) + " - " +
642  MythDate::toString(endts, date_format | MythDate::kTime);
643 
645  {
646 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
647  QDateTime ldt =
648  QDateTime(MythDate::current().toLocalTime().date(), m_findtime,
649  Qt::LocalTime);
650 #else
651  QDateTime ldt =
652  QDateTime(MythDate::current().toLocalTime().date(), m_findtime, utc);
653 #endif
654  QString findfrom = MythDate::toString(ldt, date_format | MythDate::kTime);
655  if (m_type == kWeeklyRecord)
656  {
657  int daynum = ((m_findday + 5) % 7) + 1;
658  findfrom = QString("%1, %2")
659  .arg(gCoreContext->GetQLocale().dayName(daynum, QLocale::ShortFormat),
660  findfrom);
661  }
662  infoMap["subtitle"] = tr("(%1 or later) %3",
663  "e.g. (Sunday or later) program "
664  "subtitle").arg(findfrom, m_subtitle);
665  }
666 
667  infoMap["searchtype"] = SearchTypeToString(m_searchType);
668  if (m_searchType != kNoSearch)
669  infoMap["searchforwhat"] = m_description;
670 
671  using namespace MythDate;
672  if (m_nextRecording.isValid())
673  {
674  infoMap["nextrecording"] = MythDate::toString(
675  m_nextRecording, date_format | kDateFull | kAddYear);
676  }
677  if (m_lastRecorded.isValid())
678  {
679  infoMap["lastrecorded"] = MythDate::toString(
680  m_lastRecorded, date_format | kDateFull | kAddYear);
681  }
682  if (m_lastDeleted.isValid())
683  {
684  infoMap["lastdeleted"] = MythDate::toString(
685  m_lastDeleted, date_format | kDateFull | kAddYear);
686  }
687 
688  infoMap["ruletype"] = toString(m_type);
689  infoMap["rectype"] = toString(m_type);
690  infoMap["autoextend"] = toString(m_autoExtend);
691 
692  if (m_template == "Default")
693  infoMap["template"] = tr("Default", "Default template");
694  else
695  infoMap["template"] = m_template;
696 }
697 
698 void RecordingRule::UseTempTable(bool usetemp, const QString& table)
699 {
701 
702  if (usetemp)
703  {
704  m_recordTable = table;
705 
706  query.prepare("SELECT GET_LOCK(:LOCK, 2);");
707  query.bindValue(":LOCK", "DiffSchedule");
708  if (!query.exec())
709  {
710  MythDB::DBError("Obtaining lock in testRecording", query);
711  return;
712  }
713 
714  query.prepare(QString("DROP TABLE IF EXISTS %1;").arg(table));
715  if (!query.exec())
716  {
717  MythDB::DBError("Deleting old table in testRecording", query);
718  return;
719  }
720 
721  query.prepare(QString("CREATE TABLE %1 SELECT * FROM record;")
722  .arg(table));
723  if (!query.exec())
724  {
725  MythDB::DBError("Create new temp table", query);
726  return;
727  }
728 
729  query.prepare(QString("ALTER TABLE %1 MODIFY recordid int(10) "
730  "UNSIGNED NOT NULL AUTO_INCREMENT primary key;")
731  .arg(table));
732  if (!query.exec())
733  {
734  MythDB::DBError("Modify recordid column to include "
735  "auto-increment", query);
736  return;
737  }
738 
739  if (m_recordID > 0)
741 
742  Save(false);
743  }
744  else
745  {
746  query.prepare("SELECT RELEASE_LOCK(:LOCK);");
747  query.bindValue(":LOCK", "DiffSchedule");
748  if (!query.exec())
749  {
750  MythDB::DBError("Free lock", query);
751  return;
752  }
753  m_recordTable = "record";
754  m_tempID = 0;
755  }
756 }
757 
759 {
760  if (!m_progInfo)
761  return;
762 
776  if (m_recordID <= 0)
777  {
778  m_findday =
779  (m_progInfo->GetScheduledStartTime().toLocalTime().date()
780  .dayOfWeek() + 1) % 7;
781  m_findtime = m_progInfo->GetScheduledStartTime().toLocalTime().time();
782  m_findid = QDate(1970, 1, 1).daysTo(
783  m_progInfo->GetScheduledStartTime().toLocalTime().date()) + 719528;
784  }
785  else
786  {
787  if (m_findid > 0)
789  else
790  {
791  QDate epoch(1970, 1, 1);
792  m_findid = epoch.daysTo(
793  m_progInfo->GetScheduledStartTime().toLocalTime().date())
794  + 719528;
795  }
796  }
798 
799  if (m_inetref.isEmpty())
800  {
804  }
806 }
807 
809 {
810  MSqlQuery query(MSqlQuery::InitCon());
811  query.prepare("SELECT SUM(1 << filterid) FROM recordfilter "
812  "WHERE filterid >= 0 AND filterid < :NUMFILTERS AND "
813  " TRIM(clause) <> '' AND newruledefault <> 0");
814  query.bindValue(":NUMFILTERS", RecordingRule::kNumFilters);
815  if (!query.exec())
816  {
817  MythDB::DBError("GetDefaultFilter", query);
818  return 0;
819  }
820 
821  if (!query.next())
822  return 0;
823 
824  return query.value(0).toUInt();
825 }
826 
828 {
829  QString searchTypeString;
830 
831  switch (searchType)
832  {
833  case kNoSearch:
834  searchTypeString = ""; // Allow themers to decide what to display
835  break;
836  case kPowerSearch:
837  searchTypeString = tr("Power Search");
838  break;
839  case kTitleSearch:
840  searchTypeString = tr("Title Search");
841  break;
842  case kKeywordSearch:
843  searchTypeString = tr("Keyword Search");
844  break;
845  case kPeopleSearch:
846  searchTypeString = tr("People Search");
847  break;
848  default:
849  searchTypeString = tr("Unknown Search");
850  break;
851  }
852 
853  return searchTypeString;
854 }
855 
857 {
858  QStringList result;
859 
860  MSqlQuery query(MSqlQuery::InitCon());
861  query.prepare("SELECT category "
862  "FROM record "
863  "WHERE type = :TEMPLATE "
864  "ORDER BY category = 'Default' DESC, category"
865  );
866  query.bindValue(":TEMPLATE", kTemplateRecord);
867 
868  if (!query.exec())
869  {
870  MythDB::DBError("LoadByTemplate", query);
871  return result;
872  }
873 
874  while (query.next())
875  result << query.value(0).toString();
876 
877  return result;
878 }
879 
880 bool RecordingRule::IsValid(QString &msg) const
881 {
882  bool isOverride = false;
883  switch (m_type)
884  {
885  case kSingleRecord:
886  case kDailyRecord:
887  case kAllRecord:
888  case kWeeklyRecord:
889  case kOneRecord:
890  case kTemplateRecord:
891  break;
892  case kOverrideRecord:
893  case kDontRecord:
894  isOverride = true;
895  break;
896  case kNotRecording:
897  default:
898  msg = QString("Invalid recording type.");
899  return false;
900  }
901 
902  bool isNormal = false;
903  bool isSearch = false;
904  bool isManual = false;
905  switch (m_searchType)
906  {
907  case kNoSearch:
908  isNormal = true;
909  break;
910  case kPowerSearch:
911  case kTitleSearch:
912  case kKeywordSearch:
913  case kPeopleSearch:
914  isSearch = true;
915  break;
916  case kManualSearch:
917  isManual = true;
918  break;
919  default:
920  msg = QString("Invalid search type.");
921  return false;
922  }
923 
924  if ((isNormal && (m_type == kDailyRecord || m_type == kWeeklyRecord)) ||
925  (isSearch && (m_type != kDailyRecord && m_type != kWeeklyRecord &&
926  m_type != kOneRecord && m_type != kAllRecord)) ||
927  (isManual && (m_type != kDailyRecord && m_type != kWeeklyRecord &&
929  {
930  msg = QString("Invalid recording type/search type.");
931  return false;
932  }
933 
934  if ((m_parentRecID && !isOverride) ||
935  (!m_parentRecID && isOverride))
936  {
937  msg = QString("Invalid parentID/override.");
938  return false;
939  }
940 
941  // Inactive overrides cause errors so are disallowed.
942  if (isOverride && m_isInactive)
943  {
944  msg = QString("Invalid Inactive Override.");
945  return false;
946  }
947 
948  if (m_title.isEmpty())
949  {
950  msg = QString("Invalid title.");
951  return false;
952  }
953 
954  if (m_searchType == kPowerSearch)
955  {
956  if (m_description.contains(';') || m_subtitle.contains(';'))
957  {
958  msg = QString("Invalid SQL, contains semicolon");
959  return false;
960  }
961  MSqlQuery query(MSqlQuery::InitCon());
962  query.prepare(QString("SELECT NULL FROM (program, channel, oldrecorded AS oldrecstatus) "
963  "%1 WHERE %2 LIMIT 5")
964  .arg(m_subtitle, m_description));
965  if (!query.exec())
966  {
967  msg = QString("Invalid SQL Where clause." + query.lastError().databaseText());
968  return false;
969  }
970  }
971  else if (isSearch)
972  {
973  if (m_description.isEmpty())
974  {
975  msg = QString("Invalid search value.");
976  return false;
977  }
978  }
979 
980  if (m_type != kTemplateRecord && !isSearch)
981  {
982  if (!m_startdate.isValid() || !m_starttime.isValid() ||
983  !m_enddate.isValid() || !m_endtime.isValid())
984  {
985  msg = QString("Invalid start/end date/time.");
986  return false;
987  }
988 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
989  qint64 secsto = QDateTime(m_startdate, m_starttime, Qt::UTC)
990  .secsTo(QDateTime(m_enddate, m_endtime, Qt::UTC));
991 #else
992  static const QTimeZone utc(QTimeZone::UTC);
993  qint64 secsto = QDateTime(m_startdate, m_starttime, utc)
994  .secsTo(QDateTime(m_enddate, m_endtime, utc));
995 #endif
996  if (secsto <= 0 || secsto > (8 * 3600))
997  {
998  msg = QString("Invalid duration.");
999  return false;
1000  }
1001 
1002  if (!m_channelid || m_station.isEmpty())
1003  {
1004  msg = QString("Invalid channel.");
1005  return false;
1006  }
1007  }
1008 
1009  if (m_type != kTemplateRecord
1010  && (m_findday < 0 || m_findday > 6 || !m_findtime.isValid()) )
1011  {
1012  msg = QString("Invalid find values.");
1013  return false;
1014  }
1015 
1016  if (m_recPriority < -99 || m_recPriority > 99)
1017  {
1018  msg = QString("Invalid priority.");
1019  return false;
1020  }
1021 
1022  if (m_startOffset < -480 || m_startOffset > 480 ||
1023  m_endOffset < -480 || m_endOffset > 480)
1024  {
1025  msg = QString("Invalid start/end offset.");
1026  return false;
1027  }
1028 
1029  if (m_prefInput < 0)
1030  {
1031  msg = QString("Invalid preferred input.");
1032  return false;
1033  }
1034 
1035  unsigned valid_mask = (1 << kNumFilters) - 1;
1036  if ((m_filter & valid_mask) != m_filter)
1037  {
1038  msg = QString("Invalid filter value.");
1039  return false;
1040  }
1041 
1042  if (m_recProfile.isEmpty() || (m_recGroupID == 0) ||
1043  m_storageGroup.isEmpty() || m_playGroup.isEmpty())
1044  {
1045  msg = QString("Invalid group value.");
1046  return false;
1047  }
1048 
1049  if (m_maxEpisodes < 0)
1050  {
1051  msg = QString("Invalid max episodes value.");
1052  return false;
1053  }
1054 
1055  if (m_dupIn & ~(kDupsInAll | kDupsNewEpi))
1056  {
1057  msg = QString("Invalid duplicate scope.");
1058  return false;
1059  }
1060 
1063  {
1064  msg = QString("Invalid duplicate method.");
1065  return false;
1066  }
1067 
1068  if (m_transcoder < 0)
1069  {
1070  msg = QString("Invalid transcoder value.");
1071  return false;
1072  }
1073 
1075  {
1076  msg = QString("Invalid auto extend value.");
1077  return false;
1078  }
1079 
1080  return true;
1081 }
RecordingRule::m_isOverride
bool m_isOverride
Definition: recordingrule.h:152
RecordingRule::m_channelid
int m_channelid
callsign?
Definition: recordingrule.h:99
ProgramInfo::GetSortTitle
QString GetSortTitle(void) const
Definition: programinfo.h:363
kDupsNewEpi
@ kDupsNewEpi
Definition: recordingtypes.h:50
RecordingRule::LoadByProgram
bool LoadByProgram(const ProgramInfo *proginfo)
Definition: recordingrule.cpp:170
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
kKeywordSearch
@ kKeywordSearch
Definition: recordingtypes.h:82
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
RecordingRule::m_autoTranscode
bool m_autoTranscode
Definition: recordingrule.h:132
RecordingRule::ModifyPowerSearchByID
bool ModifyPowerSearchByID(int rid, const QString &textname, QString forwhat, QString joininfo="")
Definition: recordingrule.cpp:349
RecordingRule::m_enddate
QDate m_enddate
Definition: recordingrule.h:90
RecordingRule::m_recordTable
QString m_recordTable
Definition: recordingrule.h:147
RecordingRule::m_playGroup
QString m_playGroup
Definition: recordingrule.h:122
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
RecordingRule::m_seriesid
QString m_seriesid
Definition: recordingrule.h:84
RecordingRule::m_parentRecID
int m_parentRecID
Definition: recordingrule.h:71
kWeeklyRecord
@ kWeeklyRecord
Definition: recordingtypes.h:26
RecordingRule::m_description
QString m_description
Definition: recordingrule.h:81
RecordingRule::m_template
QString m_template
Definition: recordingrule.h:163
RecordingRule::m_autoCommFlag
bool m_autoCommFlag
Definition: recordingrule.h:131
RecordingRule::m_inetref
QString m_inetref
Definition: recordingrule.h:87
getMythSortHelper
std::shared_ptr< MythSortHelper > getMythSortHelper(void)
Get a pointer to the MythSortHelper singleton.
Definition: mythsorthelper.cpp:129
kDupsInAll
@ kDupsInAll
Definition: recordingtypes.h:49
mythdb.h
RecordingRule::m_maxNewest
bool m_maxNewest
Definition: recordingrule.h:127
RecordingRule::m_category
QString m_category
Definition: recordingrule.h:82
RecordingRule::Save
bool Save(bool sendSig=true)
Definition: recordingrule.cpp:392
RecordingRule::m_nextRecording
QDateTime m_nextRecording
Definition: recordingrule.h:142
RecordingRule::m_starttime
QTime m_starttime
Definition: recordingrule.h:91
MythDate::as_utc
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:28
PlayGroup::GetInitialName
static QString GetInitialName(const ProgramInfo *pi)
Definition: playgroup.cpp:228
RecordingRule::GetDefaultFilter
static unsigned GetDefaultFilter(void)
Definition: recordingrule.cpp:808
RecordingRule::m_progInfo
const ProgramInfo * m_progInfo
Definition: recordingrule.h:167
kTitleSearch
@ kTitleSearch
Definition: recordingtypes.h:81
RecordingRule::ToMap
void ToMap(InfoMap &infoMap, uint date_format=0) const
Definition: recordingrule.cpp:554
MSqlQuery::lastInsertId
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:935
RecordingRule::m_title
QString m_title
Definition: recordingrule.h:77
RecordingRule::m_sortSubtitle
QString m_sortSubtitle
Definition: recordingrule.h:80
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
kNotRecording
@ kNotRecording
Definition: recordingtypes.h:21
ProgramInfo::GetChannelSchedulingID
QString GetChannelSchedulingID(void) const
This is the unique programming identifier of a channel.
Definition: programinfo.h:384
ProgramInfo::GetCategory
QString GetCategory(void) const
Definition: programinfo.h:370
RecordingRule::m_averageDelay
int m_averageDelay
Definition: recordingrule.h:141
RecordingRule::m_lastDeleted
QDateTime m_lastDeleted
Definition: recordingrule.h:144
RecSearchType
RecSearchType
Definition: recordingtypes.h:77
RecordingRule::m_endOffset
int m_endOffset
Definition: recordingrule.h:110
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
RecordingRule::kNumFilters
static const int kNumFilters
Definition: recordingrule.h:33
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:398
playgroup.h
kSingleRecord
@ kSingleRecord
Definition: recordingtypes.h:22
kPeopleSearch
@ kPeopleSearch
Definition: recordingtypes.h:83
mythsorthelper.h
RecordingRule::m_dupIn
RecordingDupInType m_dupIn
Definition: recordingrule.h:114
AutoExtendType
AutoExtendType
Definition: recordingtypes.h:92
RecordingRule::m_isInactive
bool m_isInactive
Recording rule is enabled?
Definition: recordingrule.h:74
RecordingRule::m_season
uint m_season
Definition: recordingrule.h:94
MythDate::kDateTimeShort
@ kDateTimeShort
Default local time.
Definition: mythdate.h:24
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
kDupCheckDesc
@ kDupCheckDesc
Definition: recordingtypes.h:66
RecordingRule::m_findid
int m_findid
Definition: recordingrule.h:102
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
kDontRecord
@ kDontRecord
Definition: recordingtypes.h:29
kDupCheckNone
@ kDupCheckNone
Definition: recordingtypes.h:64
RecordingRule::Load
bool Load(bool asTemplate=false)
Load a single rule from the recorded table.
Definition: recordingrule.cpp:58
ProgramInfo::GetInetRef
QString GetInetRef(void) const
Definition: programinfo.h:441
RecordingRule::m_startOffset
int m_startOffset
Definition: recordingrule.h:109
RecordingRule::GetTemplateNames
static QStringList GetTemplateNames(void)
Definition: recordingrule.cpp:856
RecordingRule::m_isTemplate
bool m_isTemplate
Definition: recordingrule.h:156
RecordingRule::m_episode
uint m_episode
Definition: recordingrule.h:95
mythdate.h
RecordingRule::RecordingRule
RecordingRule()
Definition: recordingrule.cpp:29
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:391
RecordingRule::IsValid
bool IsValid(QString &msg) const
Definition: recordingrule.cpp:880
kOneRecord
@ kOneRecord
Definition: recordingtypes.h:27
MythSortHelper::doTitle
QString doTitle(const QString &title) const
Create the sortable form of an title string.
Definition: mythsorthelper.cpp:163
AutoExtendType::Last
@ Last
MythCoreContext::GetQLocale
QLocale GetQLocale(void)
Definition: mythcorecontext.cpp:1882
RecordingRule::m_autoUserJob4
bool m_autoUserJob4
Definition: recordingrule.h:136
RecordingInfo::GetRecgroupString
static QString GetRecgroupString(uint recGroupID)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1729
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:362
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
ProgramInfo::GetDescription
QString GetDescription(void) const
Definition: programinfo.h:366
RecordingRule::m_autoUserJob2
bool m_autoUserJob2
Definition: recordingrule.h:134
kDupCheckSub
@ kDupCheckSub
Definition: recordingtypes.h:65
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
RecordingRule::AssignProgramInfo
void AssignProgramInfo()
Definition: recordingrule.cpp:758
RecordingRule::m_findtime
QTime m_findtime
Time for timeslot rules.
Definition: recordingrule.h:101
RecordingRule::m_lastRecorded
QDateTime m_lastRecorded
Definition: recordingrule.h:143
RecordingRule::m_autoExpire
bool m_autoExpire
Definition: recordingrule.h:126
kNoSearch
@ kNoSearch
Definition: recordingtypes.h:79
RecordingRule::m_recProfile
QString m_recProfile
Definition: recordingrule.h:120
RecordingRule::m_tempID
int m_tempID
Definition: recordingrule.h:148
kManualSearch
@ kManualSearch
Definition: recordingtypes.h:84
RecordingRule::m_searchType
RecSearchType m_searchType
Definition: recordingrule.h:112
RecordingRule::m_type
RecordingType m_type
Definition: recordingrule.h:111
kDupCheckSubThenDesc
@ kDupCheckSubThenDesc
Definition: recordingtypes.h:68
RecordingRule::m_subtitle
QString m_subtitle
Definition: recordingrule.h:79
RecordingRule::UseTempTable
void UseTempTable(bool usetemp, const QString &table="record_tmp")
Definition: recordingrule.cpp:698
MSqlQuery::SchedCon
static MSqlQueryInfo SchedCon()
Returns dedicated connection. (Required for using temporary SQL tables.)
Definition: mythdbcon.cpp:580
scheduledrecording.h
kOverrideRecord
@ kOverrideRecord
Definition: recordingtypes.h:28
RecordingRule::m_findday
int m_findday
Day of the week for once per week etc.
Definition: recordingrule.h:104
RecordingRule::m_filter
unsigned m_filter
Definition: recordingrule.h:115
ProgramInfo::GetFindID
uint GetFindID(void) const
Definition: programinfo.h:472
kDailyRecord
@ kDailyRecord
Definition: recordingtypes.h:23
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
ProgramInfo::GetSeriesID
QString GetSeriesID(void) const
Definition: programinfo.h:439
RecordingRule::MakeTemplate
bool MakeTemplate(QString category)
Definition: recordingrule.cpp:321
RecordingRule::m_maxEpisodes
int m_maxEpisodes
Definition: recordingrule.h:125
ProgramInfo::GetSortSubtitle
QString GetSortSubtitle(void) const
Definition: programinfo.h:365
RecordingRule::m_programid
QString m_programid
Definition: recordingrule.h:85
RecordingRule::m_sortTitle
QString m_sortTitle
Definition: recordingrule.h:78
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
RecordingRule::m_recGroupID
uint m_recGroupID
Definition: recordingrule.h:123
RecordingRule::m_endtime
QTime m_endtime
Definition: recordingrule.h:92
MythDate::kSimplify
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:26
MSqlQuery::lastError
QSqlError lastError(void) const
Definition: mythdbcon.h:213
RecordingRule::m_storageGroup
QString m_storageGroup
Definition: recordingrule.h:121
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:373
ProgramInfo::GetEpisode
uint GetEpisode(void) const
Definition: programinfo.h:368
RecordingRule::m_transcoder
int m_transcoder
Definition: recordingrule.h:130
RecordingRule::m_autoUserJob1
bool m_autoUserJob1
Definition: recordingrule.h:133
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
RecordingRule::LoadTemplate
bool LoadTemplate(const QString &title, const QString &category="Default", const QString &categoryType="Default")
Definition: recordingrule.cpp:278
RecordingRule::m_recordID
int m_recordID
Unique Recording Rule ID.
Definition: recordingrule.h:70
MythDate::kAddYear
@ kAddYear
Add year to string if not included.
Definition: mythdate.h:25
ProgramInfo::GetSeason
uint GetSeason(void) const
Definition: programinfo.h:367
mythcorecontext.h
RecordingRule::m_dupMethod
RecordingDupMethodType m_dupMethod
Definition: recordingrule.h:113
kTemplateRecord
@ kTemplateRecord
Definition: recordingtypes.h:32
MythDate
Definition: mythdate.cpp:12
ProgramInfo::GetCategoryTypeString
QString GetCategoryTypeString(void) const
Returns catType as a string.
Definition: programinfo.cpp:1908
kPowerSearch
@ kPowerSearch
Definition: recordingtypes.h:80
RecordingRule::ensureSortFields
void ensureSortFields(void)
Ensure that the sortTitle and sortSubtitle fields are set.
Definition: recordingrule.cpp:45
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
RecordingDupMethodType
RecordingDupMethodType
Definition: recordingtypes.h:61
RecordingType
RecordingType
Definition: recordingtypes.h:19
RecordingRule::m_autoExtend
AutoExtendType m_autoExtend
Definition: recordingrule.h:116
RecordingRule::m_loaded
bool m_loaded
Definition: recordingrule.h:171
kAllRecord
@ kAllRecord
Definition: recordingtypes.h:25
RecordingRule::Delete
bool Delete(bool sendSig=true)
Definition: recordingrule.cpp:511
MythDate::kDateFull
@ kDateFull
Default local time.
Definition: mythdate.h:19
RecordingRule::MakeOverride
bool MakeOverride(void)
Definition: recordingrule.cpp:370
recordingprofile.h
ProgramInfo::GetProgramID
QString GetProgramID(void) const
Definition: programinfo.h:440
RecordingProfile
Definition: recordingprofile.h:41
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:23
RecordingRule::m_station
QString m_station
Definition: recordingrule.h:98
MythDate::kTime
@ kTime
Default local time.
Definition: mythdate.h:22
ProgramInfo::GetRecordingRuleID
uint GetRecordingRuleID(void) const
Definition: programinfo.h:453
recordingrule.h
RecordingRule::m_recPriority
int m_recPriority
Definition: recordingrule.h:107
RecordingRule::m_autoUserJob3
bool m_autoUserJob3
Definition: recordingrule.h:135
ScheduledRecording::RescheduleMatch
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
Definition: scheduledrecording.h:17
RecordingRule::LoadBySearch
bool LoadBySearch(RecSearchType lsearch, const QString &textname, const QString &forwhat, QString joininfo="", ProgramInfo *pginfo=nullptr)
Load a recording rule based on search parameters.
Definition: recordingrule.cpp:218
RecordingDupInType
RecordingDupInType
Definition: recordingtypes.h:44
RecordingRule::m_startdate
QDate m_startdate
Definition: recordingrule.h:89
RecordingRule::m_autoMetadataLookup
bool m_autoMetadataLookup
Definition: recordingrule.h:137
null_to_empty
static QString null_to_empty(const QString &str)
Definition: recordingrule.cpp:19
RecordingRule::m_prefInput
int m_prefInput
Definition: recordingrule.h:108
uint
unsigned int uint
Definition: freesurround.h:24
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
RecordingRule::SearchTypeToString
static QString SearchTypeToString(RecSearchType searchType)
Definition: recordingrule.cpp:827
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:364