MythTV  master
schedulecommon.cpp
Go to the documentation of this file.
1 
2 #include "schedulecommon.h"
3 
4 // QT
5 #include <QCoreApplication>
6 
7 // libmyth
8 #include "mythcorecontext.h"
9 #include "programinfo.h"
10 #include "remoteutil.h"
11 
12 // libmythtv
13 #include "recordinginfo.h"
14 #include "tvremoteutil.h"
15 
16 // libmythui
17 #include "mythscreentype.h"
18 #include "mythdialogbox.h"
19 #include "mythmainwindow.h"
20 
21 // mythfrontend
22 #include "scheduleeditor.h"
23 
24 #include "proglist.h"
25 #include "prevreclist.h"
26 #include "customedit.h"
27 #include "guidegrid.h"
28 #include "progdetails.h"
29 
34 {
35  ProgramInfo *pginfo = GetCurrentProgram();
36  if (!pginfo)
37  return;
38 
40  ProgDetails *details_dialog = new ProgDetails(mainStack, pginfo);
41 
42  if (!details_dialog->Create())
43  {
44  delete details_dialog;
45  return;
46  }
47 
48  mainStack->AddScreen(details_dialog);
49 }
50 
54 void ScheduleCommon::ShowUpcoming(const QString &title,
55  const QString &seriesid) const
56 {
57  if (title.isEmpty())
58  return;
59 
61  ProgLister *pl = new ProgLister(mainStack, plTitle, title, seriesid);
62  if (pl->Create())
63  {
64  mainStack->AddScreen(pl);
65  }
66  else
67  delete pl;
68 }
69 
74 {
75  ProgramInfo *pginfo = GetCurrentProgram();
76  if (!pginfo)
77  return;
78 
79  if (pginfo->GetChanID() == 0 &&
80  pginfo->GetRecordingRuleID() > 0)
81  return ShowUpcomingScheduled();
82 
83  ShowUpcoming(pginfo->GetTitle(), pginfo->GetSeriesID());
84 }
85 
90 {
91  ProgramInfo *pginfo = GetCurrentProgram();
92  if (!pginfo)
93  return;
94 
95  RecordingInfo ri(*pginfo);
96  uint id;
97 
98  if ((id = ri.GetRecordingRuleID()) == 0)
99  return ShowUpcoming(pginfo->GetTitle(), pginfo->GetSeriesID());
100 
102  ProgLister *pl = new ProgLister(mainStack, plRecordid,
103  QString::number(id), "");
104 
105  if (pl->Create())
106  mainStack->AddScreen(pl);
107  else
108  delete pl;
109 }
110 
115 {
116  ProgramInfo *pginfo = GetCurrentProgram();
117  if (!pginfo)
118  return;
119 
121  ProgLister *pl = new ProgLister(mainStack, plChannel,
122  QString::number(pginfo->GetChanID()), "",
123  pginfo->GetScheduledStartTime());
124  if (pl->Create())
125  mainStack->AddScreen(pl);
126  else
127  delete pl;
128 }
129 
134 {
135  ProgramInfo *pginfo = GetCurrentProgram();
136  if (!pginfo)
137  return;
138 
139  QString startchannel = pginfo->GetChanNum();
140  uint startchanid = pginfo->GetChanID();
141  QDateTime starttime = pginfo->GetScheduledStartTime();
142  GuideGrid::RunProgramGuide(startchanid, startchannel, starttime);
143 }
144 
149 {
150  ProgramInfo *pginfo = GetCurrentProgram();
151  if (!pginfo)
152  return;
153 
154  if (pginfo->GetRecordingRuleID())
155  EditRecording();
156  else
157  {
158  RecordingInfo ri(*pginfo);
159  ri.QuickRecord();
160  *pginfo = ri;
161  }
162 }
163 
168 {
170 }
171 
176 {
177  if (!pginfo)
178  return;
179 
180  RecordingInfo ri(*pginfo);
181  EditScheduled(&ri);
182 }
183 
188 {
190  ScheduleEditor *schededit = new ScheduleEditor(mainStack, recinfo);
191  if (schededit->Create())
192  mainStack->AddScreen(schededit);
193  else
194  {
195  delete schededit;
196  ShowOkPopup(tr("Recording rule does not exist."));
197  }
198 }
199 
204 {
205  ProgramInfo *pginfo = GetCurrentProgram();
206  if (!pginfo)
207  return;
208 
210  CustomEdit *ce = new CustomEdit(mainStack, pginfo);
211  if (ce->Create())
212  mainStack->AddScreen(ce);
213  else
214  delete ce;
215 }
216 
221 {
222  if (!recinfo || !recinfo->GetRecordingRuleID())
223  return;
224 
225  RecordingRule *recrule = new RecordingRule();
226 
227  if (!recrule->LoadByProgram(static_cast<ProgramInfo*>(recinfo)))
228  LOG(VB_GENERAL, LOG_ERR, "Failed to load by program info");
229 
230  if (!recrule->MakeOverride())
231  {
232  LOG(VB_GENERAL, LOG_ERR, "Failed to make Override");
233  delete recrule;
234  return;
235  }
236  recrule->m_type = kOverrideRecord;
237 
239  ScheduleEditor *schededit = new ScheduleEditor(mainStack, recrule);
240  if (schededit->Create())
241  mainStack->AddScreen(schededit);
242  else
243  delete schededit;
244 }
245 
250 {
251  ProgramInfo *pginfo = GetCurrentProgram();
252  if (!pginfo)
253  return;
254 
255  ShowPrevious(pginfo->GetRecordingRuleID(), pginfo->GetTitle());
256 }
257 
261 void ScheduleCommon::ShowPrevious(uint ruleid, const QString &title) const
262 {
264  PrevRecordedList *pl = new PrevRecordedList(mainStack, ruleid, title);
265  if (pl->Create())
266  mainStack->AddScreen(pl);
267  else
268  delete pl;
269 }
270 
275 void ScheduleCommon::EditRecording(bool may_watch_now)
276 {
277  ProgramInfo *pginfo = GetCurrentProgram();
278  if (!pginfo)
279  return;
280 
281  RecordingInfo recinfo(*pginfo);
282 
283  QString timeFormat = gCoreContext->GetSetting("TimeFormat", "h:mm AP");
284 
285  QString message = recinfo.toString(ProgramInfo::kTitleSubtitle, " - ");
286 
287  message += "\n\n";
288  message += RecStatus::toDescription(recinfo.GetRecordingStatus(),
289  recinfo.GetRecordingRuleType(),
290  recinfo.GetRecordingStartTime());
291 
292  if (recinfo.GetRecordingStatus() == RecStatus::Conflict ||
294  {
295  vector<ProgramInfo *> *confList = RemoteGetConflictList(&recinfo);
296 
297  if (!confList->empty())
298  {
299  message += " ";
300  message += tr("The following programs will be recorded instead:");
301  message += "\n";
302  }
303 
304  uint maxi = 0;
305  for (; confList->begin() != confList->end() && maxi < 4; maxi++)
306  {
307  ProgramInfo *p = *confList->begin();
308  message += QString("%1 - %2 %3\n")
309  .arg(p->GetRecordingStartTime()
310  .toLocalTime().toString(timeFormat))
311  .arg(p->GetRecordingEndTime()
312  .toLocalTime().toString(timeFormat))
313  .arg(p->toString(ProgramInfo::kTitleSubtitle, " - "));
314  delete p;
315  confList->erase(confList->begin());
316  }
317  message += "\n";
318  while (!confList->empty())
319  {
320  delete confList->back();
321  confList->pop_back();
322  }
323  delete confList;
324  }
325 
326  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
327  MythDialogBox *menuPopup = new MythDialogBox(message, popupStack,
328  "recOptionPopup", true);
329  if (!menuPopup->Create())
330  {
331  delete menuPopup;
332  return;
333  }
334  menuPopup->SetReturnEvent(this, "editrecording");
335 
336  QDateTime now = MythDate::current();
337 
338  if(may_watch_now)
339  menuPopup->AddButton(tr("Watch This Channel"));
340 
341  if (recinfo.GetRecordingStatus() == RecStatus::Unknown)
342  {
343  if (recinfo.GetRecordingEndTime() > now)
344  menuPopup->AddButton(tr("Record this showing"),
345  qVariantFromValue(recinfo));
346  menuPopup->AddButton(tr("Record all showings"),
347  qVariantFromValue(recinfo));
348  if (!recinfo.IsGeneric())
349  {
351  menuPopup->AddButton(tr("Record one showing"),
352  qVariantFromValue(recinfo));
353  else
354  menuPopup->AddButton(tr("Record one showing (this episode)"),
355  qVariantFromValue(recinfo));
356 
357  }
358  menuPopup->AddButton(tr("Record all showings (this channel)"),
359  qVariantFromValue(recinfo));
360  menuPopup->AddButton(tr("Edit recording rule"),
361  qVariantFromValue(recinfo));
362  }
363  else if (recinfo.GetRecordingStatus() == RecStatus::Recording ||
364  recinfo.GetRecordingStatus() == RecStatus::Tuning ||
365  recinfo.GetRecordingStatus() == RecStatus::Failing ||
367  {
368  if (recinfo.GetRecordingStatus() != RecStatus::Pending)
369  menuPopup->AddButton(tr("Stop this recording"),
370  qVariantFromValue(recinfo));
371  menuPopup->AddButton(tr("Modify recording options"),
372  qVariantFromValue(recinfo));
373  }
374  else
375  {
376  if (recinfo.GetRecordingStartTime() < now &&
377  recinfo.GetRecordingEndTime() > now &&
380  {
381  menuPopup->AddButton(tr("Restart this recording"),
382  qVariantFromValue(recinfo));
383  }
384 
385  if (recinfo.GetRecordingEndTime() > now &&
386  recinfo.GetRecordingRuleType() != kSingleRecord &&
387  recinfo.GetRecordingRuleType() != kOverrideRecord &&
394  recinfo.GetRecordingStatus() == RecStatus::Repeat ||
397  {
398  menuPopup->AddButton(tr("Record this showing"),
399  qVariantFromValue(recinfo));
400  if (recinfo.GetRecordingStartTime() > now &&
403  {
404  menuPopup->AddButton(tr("Forget previous recording"),
405  qVariantFromValue(recinfo));
406  }
407  }
408 
409  if (recinfo.GetRecordingRuleType() != kSingleRecord &&
410  recinfo.GetRecordingRuleType() != kDontRecord &&
418  {
419  if (recinfo.GetRecordingStatus() == RecStatus::WillRecord ||
421  menuPopup->AddButton(tr("Don't record this showing"),
422  qVariantFromValue(recinfo));
423 
424  const RecordingDupMethodType dupmethod =
425  recinfo.GetDuplicateCheckMethod();
426  if (recinfo.GetRecordingRuleType() != kOverrideRecord &&
427  !((recinfo.GetFindID() == 0 ||
428  !IsFindApplicable(recinfo)) &&
430  recinfo.GetProgramID().contains(QRegExp("0000$"))) &&
431  ((((dupmethod & kDupCheckNone) == 0) &&
432  !recinfo.GetProgramID().isEmpty() &&
433  (recinfo.GetFindID() != 0 ||
434  !IsFindApplicable(recinfo))) ||
435  (((dupmethod & kDupCheckSub) != 0) &&
436  !recinfo.GetSubtitle().isEmpty()) ||
437  (((dupmethod & kDupCheckDesc) != 0) &&
438  !recinfo.GetDescription().isEmpty()) ||
439  (((dupmethod & kDupCheckSubThenDesc) != 0) &&
440  (!recinfo.GetSubtitle().isEmpty() ||
441  !recinfo.GetDescription().isEmpty())) ))
442  {
443  menuPopup->AddButton(tr("Never record this episode"),
444  qVariantFromValue(recinfo));
445  }
446  }
447 
448  if (recinfo.GetRecordingRuleType() == kOverrideRecord ||
449  recinfo.GetRecordingRuleType() == kDontRecord)
450  {
451  menuPopup->AddButton(tr("Edit override rule"),
452  qVariantFromValue(recinfo));
453  menuPopup->AddButton(tr("Delete override rule"),
454  qVariantFromValue(recinfo));
455  }
456  else
457  {
458  if (recinfo.GetRecordingRuleType() != kSingleRecord &&
460  menuPopup->AddButton(tr("Add override rule"),
461  qVariantFromValue(recinfo));
462  menuPopup->AddButton(tr("Edit recording rule"),
463  qVariantFromValue(recinfo));
464  menuPopup->AddButton(tr("Delete recording rule"),
465  qVariantFromValue(recinfo));
466  }
467  }
468 
469  popupStack->AddScreen(menuPopup);
470 }
471 
472 void ScheduleCommon::customEvent(QEvent *event)
473 {
474  if (event->type() == DialogCompletionEvent::kEventType)
475  {
477 
478  QString resultid = dce->GetId();
479  QString resulttext = dce->GetResultText();
480 
481  if (resultid == "editrecording")
482  {
483  if (!dce->GetData().canConvert<RecordingInfo>())
484  return;
485 
486  RecordingInfo recInfo = dce->GetData().value<RecordingInfo>();
487 
488  if (resulttext == tr("Record this showing"))
489  {
490  if (recInfo.GetRecordingRuleType() == kNotRecording)
492  else
493  {
495  if (recInfo.GetRecordingStartTime() < MythDate::current())
496  recInfo.ReactivateRecording();
497  }
498  }
499  else if (resulttext == tr("Record all showings"))
501  else if (resulttext == tr("Record one showing (this episode)") ||
502  resulttext == tr("Record one showing"))
503  {
504  recInfo.ApplyRecordStateChange(kOneRecord, false);
505  recInfo.GetRecordingRule()->m_filter |= 64; // This episode
506  recInfo.GetRecordingRule()->Save();
507  }
508  else if (resulttext == tr("Record all showings (this channel)"))
509  {
510  recInfo.ApplyRecordStateChange(kAllRecord, false);
511  recInfo.GetRecordingRule()->m_filter |= 1024; // This channel
512  recInfo.GetRecordingRule()->Save();
513  }
514  else if (resulttext == tr("Stop this recording"))
515  {
516  RemoteStopRecording(&recInfo);
517  }
518  else if (resulttext == tr("Modify recording options") ||
519  resulttext == tr("Add override rule"))
520  {
521  if (recInfo.GetRecordingRuleType() == kSingleRecord ||
522  recInfo.GetRecordingRuleType() == kOverrideRecord ||
523  recInfo.GetRecordingRuleType() == kOneRecord)
524  EditScheduled(&recInfo);
525  else
526  MakeOverride(&recInfo);
527  }
528  else if (resulttext == tr("Restart this recording"))
529  recInfo.ReactivateRecording();
530  else if (resulttext == tr("Forget previous recording"))
531  recInfo.ForgetHistory();
532  else if (resulttext == tr("Don't record this showing"))
534  else if (resulttext == tr("Never record this episode"))
535  {
536  recInfo.ApplyNeverRecord();
537  }
538  else if (resulttext == tr("Edit recording rule") ||
539  resulttext == tr("Edit override rule"))
540  EditScheduled(&recInfo);
541  else if (resulttext == tr("Delete recording rule") ||
542  resulttext == tr("Delete override rule"))
544  }
545  }
546 }
547 
553 {
554  return recInfo.GetRecordingRuleType() == kDailyRecord ||
555  recInfo.GetRecordingRuleType() == kWeeklyRecord;
556 }
557 
void ReactivateRecording(void)
Asks the scheduler to restart this recording if possible.
bool LoadByProgram(const ProgramInfo *proginfo)
RecordingDupMethodType GetDuplicateCheckMethod(void) const
What should be compared to determine if two programs are the same?
Definition: programinfo.h:451
virtual void ShowUpcomingScheduled(void) const
Show the upcoming recordings for this recording rule.
bool Create(void) override
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
A screen to create a fully custom recording.
Definition: customedit.h:17
bool Create(void) override
Definition: proglist.cpp:98
Basic menu dialog, message and a list of options.
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
QString GetTitle(void) const
Definition: programinfo.h:353
static QString toDescription(Type, RecordingType, const QDateTime &recstartts)
Converts "recstatus" into a long human readable description.
Definition: recStatus.cpp:195
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:34
bool Create() override
Definition: customedit.cpp:51
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
MythScreenStack * GetStack(const QString &stackname)
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
RecordingType m_type
MythScreenStack * GetMainStack()
virtual void ShowDetails(void) const
Show the Program Details screen.
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:368
bool Create(void) override
static Type kEventType
Definition: mythdialogbox.h:50
bool Create(void) override
Definition: progdetails.cpp:20
RecordingDupMethodType
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:382
bool Save(bool sendSig=true)
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
Holds information on recordings and videos.
Definition: programinfo.h:66
void ApplyRecordStateChange(RecordingType newstate, bool save=true)
Sets RecordingType of "record", creating "record" if it does not exist.
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
virtual void ShowGuide(void) const
Show the program guide.
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
QString GetDescription(void) const
Definition: programinfo.h:357
Construct a recording schedule.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
QString GetSubtitle(void) const
Definition: programinfo.h:355
bool IsGeneric(void) const
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:32
virtual void EditCustom(void)
Creates a dialog for creating a custom recording rule.
void customEvent(QEvent *) override
void QuickRecord(void)
Create a kSingleRecord if not already scheduled.
MythMainWindow * GetMythMainWindow(void)
virtual void ShowChannelSearch(void) const
Show the channel search.
QString GetSeriesID(void) const
Definition: programinfo.h:427
bool RemoteStopRecording(uint inputid)
vector< ProgramInfo * > * RemoteGetConflictList(const ProgramInfo *pginfo)
Definition: remoteutil.cpp:203
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:439
virtual void QuickRecord(void)
Create a kSingleRecord or bring up recording dialog.
virtual void EditScheduled(void)
Creates a dialog for editing the recording schedule.
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:443
static void RunProgramGuide(uint startChanId, const QString &startChanNum, const QDateTime &startTime, TV *player=nullptr, bool embedVideo=false, bool allowFinder=true, int changrpid=-1)
Definition: guidegrid.cpp:418
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:364
void ApplyNeverRecord(void)
Set this program to never be recorded by inserting 'history' for it into the database with a status o...
void SetReturnEvent(QObject *retobject, const QString &resultid)
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
unsigned m_filter
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:404
void MakeOverride(RecordingInfo *recinfo)
Creates a dialog for editing an override recording schedule.
bool IsFindApplicable(const RecordingInfo &recInfo) const
Returns true if a search should be employed to find a matching program.
bool MakeOverride(void)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
CategoryType GetCategoryType(void) const
Definition: programinfo.h:430
virtual ProgramInfo * GetCurrentProgram(void) const
virtual void EditRecording(bool may_watch_now=false)
Creates a dialog for editing the recording status, blocking until user leaves dialog.
bool Create(void) override