MythTV  master
scheduleeditor.cpp
Go to the documentation of this file.
1 
2 #include "scheduleeditor.h"
3 
4 // QT
5 #include <QCoreApplication>
6 #include <QHash>
7 #include <QString>
8 #include <utility>
9 
10 // Libmyth
11 #include "mythcorecontext.h"
12 #include "storagegroup.h"
13 #include "programtypes.h"
14 #include "recordingtypes.h"
15 
16 // Libmythtv
17 #include "playgroup.h"
18 #include "tv_play.h"
19 #include "recordingprofile.h"
20 #include "cardutil.h"
21 
22 // Libmythui
23 #include "mythmainwindow.h"
24 #include "mythuihelper.h"
25 #include "mythuibuttonlist.h"
26 #include "mythuibutton.h"
27 #include "mythuitext.h"
28 #include "mythuiimage.h"
29 #include "mythuistatetype.h"
30 #include "mythuispinbox.h"
31 #include "mythuicheckbox.h"
32 #include "mythdialogbox.h"
33 #include "mythprogressdialog.h"
34 #include "mythuifilebrowser.h"
35 #include "mythuimetadataresults.h"
36 #include "mythuiimageresults.h"
37 #include "videoutils.h"
38 #include "mythuiutils.h"
39 #include "mythtypes.h"
40 
41 #include "metadataimagehelper.h"
42 
43 // Mythfrontend
44 #include "proglist.h"
45 #include "viewschedulediff.h"
46 
47 #define ENUM_TO_QVARIANT(a) qVariantFromValue(static_cast<int>(a))
48 
49 //static const QString _Location = QObject::tr("Schedule Editor");
50 
51 // Define the strings inserted into the recordfilter table in the
52 // database. This should make them available to the translators.
53 static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"));
54 static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"));
55 static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"));
56 static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"));
57 static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"));
58 static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"));
59 static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"));
60 static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"));
61 static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor", "This time"));
62 static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor", "This day and time"));
63 static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor", "This channel"));
64 static QString fs11(QT_TRANSLATE_NOOP("SchedFilterEditor", "No episodes"));
65 
66 void *ScheduleEditor::RunScheduleEditor(ProgramInfo *proginfo, void *player)
67 {
68  RecordingRule *rule = new RecordingRule();
69  rule->LoadByProgram(proginfo);
70 
72  ScheduleEditor *se = new ScheduleEditor(mainStack, rule,
73  static_cast<TV*>(player));
74 
75  if (se->Create())
76  mainStack->AddScreen(se, (player == nullptr));
77  else
78  delete se;
79 
80  return nullptr;
81 }
82 
89  RecordingInfo *recInfo, TV *player)
90  : ScheduleCommon(parent, "ScheduleEditor"),
91  SchedOptMixin(*this, nullptr), FilterOptMixin(*this, nullptr),
92  StoreOptMixin(*this, nullptr), PostProcMixin(*this, nullptr),
93  m_recInfo(new RecordingInfo(*recInfo)),
94  m_player(player)
95 {
102 }
103 
105  RecordingRule *recRule, TV *player)
106  : ScheduleCommon(parent, "ScheduleEditor"),
107  SchedOptMixin(*this, recRule),
108  FilterOptMixin(*this, recRule),
109  StoreOptMixin(*this, recRule),
110  PostProcMixin(*this, recRule),
111  m_recordingRule(recRule),
112  m_player(player), m_view(kMainView)
113 {
114 }
115 
117 {
118  delete m_recordingRule;
119 
120  // if we have a player, we need to tell we are done
121  if (m_player)
122  {
123  QString message = QString("VIEWSCHEDULED_EXITING");
124  qApp->postEvent(m_player, new MythEvent(message));
125  }
126 }
127 
129 {
130  if (!LoadWindowFromXML("schedule-ui.xml", "scheduleeditor", this))
131  return false;
132 
133  bool err = false;
134 
135  UIUtilE::Assign(this, m_rulesList, "rules", &err);
136 
137  UIUtilW::Assign(this, m_schedOptButton, "schedoptions");
138  UIUtilW::Assign(this, m_storeOptButton, "storeoptions");
139  UIUtilW::Assign(this, m_postProcButton, "postprocessing");
140  UIUtilW::Assign(this, m_metadataButton, "metadata");
141  UIUtilW::Assign(this, m_schedInfoButton, "schedinfo");
142  UIUtilW::Assign(this, m_previewButton, "preview");
143  UIUtilW::Assign(this, m_filtersButton, "filters");
144 
145  SchedOptMixin::Create(&err);
147  StoreOptMixin::Create(&err);
148  PostProcMixin::Create(&err);
149 
150  UIUtilW::Assign(this, m_cancelButton, "cancel");
151  UIUtilE::Assign(this, m_saveButton, "save", &err);
152 
153  if (err)
154  {
155  LOG(VB_GENERAL, LOG_ERR, "ScheduleEditor, theme is missing "
156  "required elements");
157  return false;
158  }
159 
160  connect(m_rulesList, SIGNAL(itemSelected(MythUIButtonListItem *)),
162 
163  if (m_schedOptButton)
164  connect(m_schedOptButton, SIGNAL(Clicked()), SLOT(ShowSchedOpt()));
165  if (m_filtersButton)
166  connect(m_filtersButton, SIGNAL(Clicked()), SLOT(ShowFilters()));
167  if (m_storeOptButton)
168  connect(m_storeOptButton, SIGNAL(Clicked()), SLOT(ShowStoreOpt()));
169  if (m_postProcButton)
170  connect(m_postProcButton, SIGNAL(Clicked()), SLOT(ShowPostProc()));
171  if (m_schedInfoButton)
172  connect(m_schedInfoButton, SIGNAL(Clicked()), SLOT(ShowSchedInfo()));
173  if (m_previewButton)
174  connect(m_previewButton, SIGNAL(Clicked()), SLOT(ShowPreview()));
175  if (m_metadataButton)
176  connect(m_metadataButton, SIGNAL(Clicked()), SLOT(ShowMetadataOptions()));
177 
178  if (m_cancelButton)
179  connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
180  connect(m_saveButton, SIGNAL(Clicked()), SLOT(Save()));
181 
182  if (m_schedInfoButton)
184  if (m_previewButton)
186 
187  if (m_dupmethodList)
188  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
190  if (m_filtersList)
191  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
193  if (m_maxepSpin)
194  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
196  if (m_recgroupList)
197  connect(m_recgroupList, SIGNAL(LosingFocus()),
198  SLOT(PromptForRecGroup()));
199  if (m_transcodeCheck)
200  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
201  SLOT(TranscodeChanged(bool)));
202 
203  BuildFocusList();
204 
205  if (!m_recordingRule->IsLoaded())
206  {
207  if (m_recInfo)
209  else if (m_recordingRule->m_recordID)
211 
212  if (!m_recordingRule->IsLoaded())
213  {
214  LOG(VB_GENERAL, LOG_ERR,
215  "ScheduleEditor::Create() - Failed to load recording rule");
216  return false;
217  }
218  }
219 
220  if (m_player)
221  m_player->StartEmbedding(QRect());
222 
223  return true;
224 }
225 
227 {
228  if (m_child)
229  m_child->Close();
230 
231  // don't fade the screen if we are returning to the player
232  if (m_player)
233  GetScreenStack()->PopScreen(this, false);
234  else
235  GetScreenStack()->PopScreen(this, true);
236 }
237 
239 {
244 
245  if (!m_loaded)
246  {
247  // Copy this now, it will change briefly after the first item
248  // is inserted into the list by design of
249  // MythUIButtonList::itemSelected()
251 
252  // Rules List
254  {
256  .compare("Default", Qt::CaseInsensitive) != 0)
257  {
259  tr("Delete this recording rule template"),
261  }
265  }
266  else if (m_recordingRule->m_isOverride)
267  {
269  tr("Record this showing with normal options"),
277  }
278  else
279  {
280  bool hasChannel = !m_recordingRule->m_station.isEmpty();
281  bool isManual = (m_recordingRule->m_searchType == kManualSearch);
282 
286  if (hasChannel)
290  if (!isManual)
294  if (!hasChannel || isManual)
298  if (!hasChannel || isManual)
302  if (!isManual)
306  }
307 
309  }
311 
312  InfoMap progMap;
313 
314  m_recordingRule->ToMap(progMap);
315 
316  if (m_recInfo)
317  m_recInfo->ToMap(progMap);
318 
319  SetTextFromMap(progMap);
320 
321  m_loaded = true;
322 }
323 
325 {
326  m_recordingRule->LoadTemplate(std::move(name));
327  Load();
328  emit templateLoaded();
329 }
330 
332 {
333  if (!item)
334  return;
335 
336  m_recordingRule->m_type = static_cast<RecordingType>
337  (item->GetData().toInt());
338 
339  bool isScheduled = (m_recordingRule->m_type != kNotRecording &&
341 
342  if (m_schedOptButton)
343  m_schedOptButton->SetEnabled(isScheduled);
344  if (m_filtersButton)
345  m_filtersButton->SetEnabled(isScheduled);
346  if (m_storeOptButton)
347  m_storeOptButton->SetEnabled(isScheduled);
348  if (m_postProcButton)
349  m_postProcButton->SetEnabled(isScheduled);
350  if (m_metadataButton)
351  m_metadataButton->SetEnabled(isScheduled &&
353 
358 }
359 
361 {
363 }
364 
366 {
368 }
369 
371 {
373 }
374 
376 {
378 }
379 
381 {
383 }
384 
386 {
387  if (m_child)
388  m_child->Close();
389 
391  {
392  int recid = m_recordingRule->m_recordID;
393  DeleteRule();
394  if (recid)
395  emit ruleDeleted(recid);
396  Close();
397  return;
398  }
399 
404  m_recordingRule->Save(true);
406 
407  Close();
408 }
409 
411 {
413 }
414 
416 {
419  return;
420 
421  if (m_child)
422  m_child->Close();
423 
425 
427  SchedOptEditor *schedoptedit = new SchedOptEditor(mainStack, *this,
429  if (!schedoptedit->Create())
430  {
431  delete schedoptedit;
432  return;
433  }
434 
436  m_child = schedoptedit;
437  mainStack->AddScreen(schedoptedit);
438 }
439 
441 {
444  return;
445 
446  if (m_child)
447  m_child->Close();
448 
450 
452  StoreOptEditor *storeoptedit = new StoreOptEditor(mainStack, *this,
454  if (!storeoptedit->Create())
455  {
456  delete storeoptedit;
457  return;
458  }
459 
461  m_child = storeoptedit;
462  mainStack->AddScreen(storeoptedit);
463 }
464 
466 {
469  return;
470 
471  if (m_child)
472  m_child->Close();
473 
475 
477  PostProcEditor *ppedit = new PostProcEditor(mainStack, *this,
479  if (!ppedit->Create())
480  {
481  delete ppedit;
482  return;
483  }
484 
486  m_child = ppedit;
487  mainStack->AddScreen(ppedit);
488 }
489 
491 {
493  return;
494 
495  QString label = tr("Schedule Information");
496 
497  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
498  MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
499 
500  if (menuPopup->Create())
501  {
502  menuPopup->SetReturnEvent(this, "schedinfo");
503 
504  if (m_recInfo)
505  menuPopup->AddButton(tr("Program Details"));
506  menuPopup->AddButton(tr("Upcoming Episodes"));
507  menuPopup->AddButton(tr("Upcoming Recordings"));
509  menuPopup->AddButton(tr("Previously Recorded"));
510 
511  popupStack->AddScreen(menuPopup);
512  }
513  else
514  delete menuPopup;
515 }
516 
517 bool ScheduleEditor::keyPressEvent(QKeyEvent *event)
518 {
519  if (GetFocusWidget()->keyPressEvent(event))
520  return true;
521 
522  QStringList actions;
523  bool handled = GetMythMainWindow()->
524  TranslateKeyPress("TV Frontend", event, actions);
525 
526  for (int i = 0; i < actions.size() && !handled; i++)
527  {
528  QString action = actions[i];
529  handled = true;
530 
531  if (action == "MENU")
532  showMenu();
533  else if (action == "INFO")
534  ShowDetails();
535  else if (action == "GUIDE")
536  ShowGuide();
537  else if (action == "UPCOMING")
539  else if (action == "PREVVIEW")
541  else if (action == "NEXTVIEW")
542  ShowNextView();
543  else
544  handled = false;
545  }
546 
547  if (!handled && MythScreenType::keyPressEvent(event))
548  handled = true;
549 
550  return handled;
551 }
552 
553 void ScheduleEditor::customEvent(QEvent *event)
554 {
555  if (event->type() == DialogCompletionEvent::kEventType)
556  {
558 
559  QString resultid = dce->GetId();
560  QString resulttext = dce->GetResultText();
561 
562  if (resultid == "menu")
563  {
564  if (resulttext == tr("Main Options"))
565  m_child->Close();
566  if (resulttext == tr("Schedule Options"))
567  ShowSchedOpt();
568  else if (resulttext == tr("Filter Options"))
569  ShowFilters();
570  else if (resulttext == tr("Storage Options"))
571  ShowStoreOpt();
572  else if (resulttext == tr("Post Processing"))
573  ShowPostProc();
574  else if (resulttext == tr("Metadata Options"))
576  else if (resulttext == tr("Use Template"))
578  else if (resulttext == tr("Schedule Info"))
579  ShowSchedInfo();
580  else if (resulttext == tr("Preview Changes"))
581  ShowPreview();
582  }
583  else if (resultid == "templatemenu")
584  {
585  LoadTemplate(resulttext);
586  }
587  else if (resultid == "schedinfo")
588  {
589  if (resulttext == tr("Program Details"))
590  ShowDetails();
591  else if (resulttext == tr("Upcoming Episodes"))
593  else if (resulttext == tr("Upcoming Recordings"))
595  else if (resulttext == tr("Previously Recorded"))
598  }
599  else if (resultid == "newrecgroup")
600  {
601  int groupID = CreateRecordingGroup(resulttext);
602  StoreOptMixin::SetRecGroup(groupID, resulttext);
603  }
604  }
605 }
606 
608 {
610  return;
611 
612  // No rule? Search by title
613  if (m_recordingRule->m_recordID <= 0)
614  {
616  return;
617  }
618 
620  ProgLister *pl = new ProgLister(mainStack, plRecordid,
621  QString::number(m_recordingRule->m_recordID),
622  "");
623 
624  if (pl->Create())
625  mainStack->AddScreen(pl);
626  else
627  delete pl;
628 }
629 
631 {
633  return;
634 
635  // Existing rule and search? Search by rule
636  if (m_recordingRule->m_recordID > 0 &&
639 
640  QString title = m_recordingRule->m_title;
641 
643  title.remove(QRegExp(" \\(.*\\)$"));
644 
646 }
647 
649 {
651  return;
652 
653  if (m_child)
654  {
655  m_child->Save();
656  if (m_view == kSchedOptView)
658  else if (m_view == kStoreOptView)
660  else if (m_view == kPostProcView)
662  }
663 
668 
669  QString ttable = "record_tmp";
670  m_recordingRule->UseTempTable(true, ttable);
671 
673  ViewScheduleDiff *vsd = new ViewScheduleDiff(mainStack, ttable,
676  if (vsd->Create())
677  mainStack->AddScreen(vsd);
678  else
679  delete vsd;
680 
682 }
683 
685 {
689  return;
690 
691  if (m_child)
692  m_child->Close();
693 
695  MetadataOptions *rad = new MetadataOptions(mainStack, *this,
697  if (!rad->Create())
698  {
699  delete rad;
700  return;
701  }
702 
704  m_child = rad;
705  mainStack->AddScreen(rad);
706 }
707 
709 {
712  return;
713 
714  if (m_child)
715  m_child->Close();
716 
718 
720  SchedFilterEditor *schedfilteredit = new SchedFilterEditor(mainStack,
721  *this, *m_recordingRule, m_recInfo);
722  if (!schedfilteredit->Create())
723  {
724  delete schedfilteredit;
725  return;
726  }
727 
729  m_child = schedfilteredit;
730  mainStack->AddScreen(schedfilteredit);
731 }
732 
734 {
737  return;
738 
741  else if (m_view == kMainView)
742  ShowPostProc();
743  else if (m_view == kSchedOptView)
744  m_child->Close();
745  else if (m_view == kFilterView)
746  ShowSchedOpt();
747  else if (m_view == kStoreOptView)
748  ShowFilters();
749  else if (m_view == kPostProcView)
750  ShowStoreOpt();
751  else if (m_view == kMetadataView)
752  ShowPostProc();
753 }
754 
756 {
759  return;
760 
761  if (m_view == kMainView)
762  ShowSchedOpt();
763  else if (m_view == kSchedOptView)
764  ShowFilters();
765  else if (m_view == kFilterView)
766  ShowStoreOpt();
767  else if (m_view == kStoreOptView)
768  ShowPostProc();
771  else if (m_view == kPostProcView)
772  m_child->Close();
773  else if (m_view == kMetadataView)
774  m_child->Close();
775 }
776 
778 {
779  if (m_view == kSchedOptView)
781  else if (m_view == kFilterView)
783  else if (m_view == kStoreOptView)
785  else if (m_view == kPostProcView)
787 
788  m_child = nullptr;
789  m_view = kMainView;
790 }
791 
793 {
794  QString label = tr("Options");
795  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
796  MythDialogBox *menuPopup =
797  new MythDialogBox(label, popupStack, "menuPopup");
798 
800  RecordingType type = static_cast<RecordingType>(item->GetData().toInt());
801  bool isScheduled = (type != kNotRecording && type != kDontRecord);
802 
803  if (menuPopup->Create())
804  {
805  menuPopup->SetReturnEvent(this, "menu");
806  if (m_view != kMainView)
807  menuPopup->AddButton(tr("Main Options"));
808  if (isScheduled && m_view != kSchedOptView)
809  menuPopup->AddButton(tr("Schedule Options"));
810  if (isScheduled && m_view != kFilterView)
811  menuPopup->AddButton(tr("Filter Options"));
812  if (isScheduled && m_view != kStoreOptView)
813  menuPopup->AddButton(tr("Storage Options"));
814  if (isScheduled && m_view != kPostProcView)
815  menuPopup->AddButton(tr("Post Processing"));
816  if (isScheduled && !m_recordingRule->m_isTemplate &&
818  menuPopup->AddButton(tr("Metadata Options"));
820  menuPopup->AddButton(tr("Schedule Info"));
822  menuPopup->AddButton(tr("Preview Changes"));
823  menuPopup->AddButton(tr("Use Template"));
824  popupStack->AddScreen(menuPopup);
825  }
826  else
827  {
828  delete menuPopup;
829  }
830 }
831 
833 {
834  QStringList templates = RecordingRule::GetTemplateNames();
835  if (templates.empty())
836  {
837  ShowOkPopup(tr("No templates available"));
838  return;
839  }
840 
841  QString label = tr("Template Options");
842  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
843  MythDialogBox *menuPopup =
844  new MythDialogBox(label, popupStack, "menuPopup");
845 
846  if (menuPopup->Create())
847  {
848  menuPopup->SetReturnEvent(this, "templatemenu");
849  while (!templates.empty())
850  {
851  QString name = templates.front();
852  if (name == "Default")
853  menuPopup->AddButton(tr("Default"));
854  else
855  menuPopup->AddButton(name);
856  templates.pop_front();
857  }
858  popupStack->AddScreen(menuPopup);
859  }
860  else
861  {
862  delete menuPopup;
863  }
864 }
865 
867 
873  ScheduleEditor &editor, RecordingRule &rule,
874  RecordingInfo *recInfo)
875  : MythScreenType(parent, name),
876  m_editor(&editor), m_recordingRule(&rule), m_recInfo(recInfo)
877 {
878 }
879 
880 bool SchedEditChild::keyPressEvent(QKeyEvent *event)
881 {
882  if (GetFocusWidget()->keyPressEvent(event))
883  return true;
884 
885  QStringList actions;
886  bool handled = GetMythMainWindow()->
887  TranslateKeyPress("TV Frontend", event, actions);
888 
889  for (int i = 0; i < actions.size() && !handled; i++)
890  {
891  QString action = actions[i];
892  handled = true;
893 
894  if (action == "MENU")
895  m_editor->showMenu();
896  else if (action == "INFO")
898  else if (action == "UPCOMING")
900  if (action == "ESCAPE")
901  Close();
902  else if (action == "PREVVIEW")
904  else if (action == "NEXTVIEW")
906  else
907  handled = false;
908  }
909 
910  if (!handled && MythScreenType::keyPressEvent(event))
911  handled = true;
912 
913  return handled;
914 }
915 
917  const QString &xmlfile, const QString &winname, bool isTemplate)
918 {
919  if (!LoadWindowFromXML(xmlfile, winname, this))
920  return false;
921 
922  UIUtilW::Assign(this, m_backButton, "back");
923  UIUtilW::Assign(this, m_saveButton, "save");
924  UIUtilW::Assign(this, m_previewButton, "preview");
925 
926  connect(this, SIGNAL(Closing()), m_editor, SLOT(ChildClosing()));
927  connect(m_editor, SIGNAL(templateLoaded()), SLOT(Load()));
928 
929  if (m_backButton)
930  connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
931  if (m_saveButton)
932  connect(m_saveButton, SIGNAL(Clicked()), m_editor, SLOT(Save()));
933  if (m_previewButton)
934  connect(m_previewButton, SIGNAL(Clicked()),
935  m_editor, SLOT(ShowPreview()));
936 
937  if (m_previewButton)
938  m_previewButton->SetEnabled(!isTemplate);
939 
940  return true;
941 }
942 
944 {
945  InfoMap progMap;
946 
947  m_recordingRule->ToMap(progMap);
948 
949  if (m_recInfo)
950  m_recInfo->ToMap(progMap);
951 
952  SetTextFromMap(progMap);
953 }
954 
956 {
957  Save();
958  emit Closing();
960 }
961 
963 
970  ScheduleEditor &editor,
971  RecordingRule &rule,
972  RecordingInfo *recInfo)
973  : SchedEditChild(parent, "ScheduleOptionsEditor", editor, rule, recInfo),
974  SchedOptMixin(*this, &rule, &editor)
975 {
976 }
977 
979 {
981  "schedule-ui.xml", "scheduleoptionseditor",
983  {
984  return false;
985  }
986 
987  bool err = false;
988 
989  SchedOptMixin::Create(&err);
990 
991  UIUtilW::Assign(this, m_filtersButton, "filters");
992 
993  if (err)
994  {
995  LOG(VB_GENERAL, LOG_ERR, "SchedOptEditor, theme is missing "
996  "required elements");
997  return false;
998  }
999 
1000  if (m_dupmethodList)
1001  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
1003 
1004  if (m_filtersButton)
1005  connect(m_filtersButton, SIGNAL(Clicked()),
1006  m_editor, SLOT(ShowFilters()));
1007 
1008  BuildFocusList();
1009 
1010  return true;
1011 }
1012 
1014 {
1016  SetTextFromMaps();
1017 }
1018 
1020 {
1022 }
1023 
1025 {
1027 }
1028 
1030 
1037  ScheduleEditor &editor,
1038  RecordingRule &rule,
1039  RecordingInfo *recInfo)
1040  : SchedEditChild(parent, "ScheduleFilterEditor", editor, rule, recInfo),
1041  FilterOptMixin(*this, &rule, &editor)
1042 {
1043 }
1044 
1046 {
1048  "schedule-ui.xml", "schedulefiltereditor",
1050  {
1051  return false;
1052  }
1053 
1054  bool err = false;
1055 
1056  FilterOptMixin::Create(&err);
1057 
1058  if (err)
1059  {
1060  LOG(VB_GENERAL, LOG_ERR, "SchedFilterEditor, theme is missing "
1061  "required elements");
1062  return false;
1063  }
1064 
1065  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
1067 
1068  BuildFocusList();
1069 
1070  return true;
1071 }
1072 
1074 {
1076  SetTextFromMaps();
1077 }
1078 
1080 {
1082 }
1083 
1085 {
1087 }
1088 
1090 
1097  ScheduleEditor &editor,
1098  RecordingRule &rule,
1099  RecordingInfo *recInfo)
1100  : SchedEditChild(parent, "StorageOptionsEditor", editor, rule, recInfo),
1101  StoreOptMixin(*this, &rule, &editor)
1102 {
1103 }
1104 
1106 {
1108  "schedule-ui.xml", "storageoptionseditor",
1110  {
1111  return false;
1112  }
1113 
1114  bool err = false;
1115 
1116  StoreOptMixin::Create(&err);
1117 
1118  if (err)
1119  {
1120  LOG(VB_GENERAL, LOG_ERR, "StoreOptEditor, theme is missing "
1121  "required elements");
1122  return false;
1123  }
1124 
1125  if (m_maxepSpin)
1126  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
1128  if (m_recgroupList)
1129  connect(m_recgroupList, SIGNAL(LosingFocus()),
1130  SLOT(PromptForRecGroup()));
1131 
1132  BuildFocusList();
1133 
1134  return true;
1135 }
1136 
1138 {
1140  SetTextFromMaps();
1141 }
1142 
1144 {
1146 }
1147 
1149 {
1151 }
1152 
1153 void StoreOptEditor::customEvent(QEvent *event)
1154 {
1155  if (event->type() == DialogCompletionEvent::kEventType)
1156  {
1158 
1159  QString resultid = dce->GetId();
1160  QString resulttext = dce->GetResultText();
1161 
1162  if (resultid == "newrecgroup")
1163  {
1164  int groupID = CreateRecordingGroup(resulttext);
1165  StoreOptMixin::SetRecGroup(groupID, resulttext);
1166  }
1167  }
1168 }
1169 
1171 {
1173 }
1174 
1176 
1183  ScheduleEditor &editor,
1184  RecordingRule &rule,
1185  RecordingInfo *recInfo)
1186  : SchedEditChild(parent, "PostProcOptionsEditor", editor, rule, recInfo),
1187  PostProcMixin(*this, &rule, &editor)
1188 {
1189 }
1190 
1192 {
1194  "schedule-ui.xml", "postproceditor",
1196  {
1197  return false;
1198  }
1199 
1200  bool err = false;
1201 
1202  PostProcMixin::Create(&err);
1203 
1204  if (err)
1205  {
1206  LOG(VB_GENERAL, LOG_ERR, "PostProcEditor, theme is missing "
1207  "required elements");
1208  return false;
1209  }
1210 
1211  if (m_transcodeCheck)
1212  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
1213  SLOT(TranscodeChanged(bool)));
1214 
1215  BuildFocusList();
1216 
1217  return true;
1218 }
1219 
1221 {
1223  SetTextFromMaps();
1224 }
1225 
1227 {
1229 }
1230 
1232 {
1234 }
1235 
1237 
1244  ScheduleEditor &editor,
1245  RecordingRule &rule,
1246  RecordingInfo *recInfo)
1247  : SchedEditChild(parent, "MetadataOptions", editor, rule, recInfo)
1248 {
1249  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
1250 
1251  m_metadataFactory = new MetadataFactory(this);
1252  m_imageLookup = new MetadataDownload(this);
1254 
1257 }
1258 
1260 {
1261  if (m_imageLookup)
1262  {
1263  m_imageLookup->cancel();
1264  delete m_imageLookup;
1265  m_imageLookup = nullptr;
1266  }
1267 
1268  if (m_imageDownload)
1269  {
1271  delete m_imageDownload;
1272  m_imageDownload = nullptr;
1273  }
1274 }
1275 
1277 {
1279  "schedule-ui.xml", "metadataoptions",
1281  {
1282  return false;
1283  }
1284 
1285  bool err = false;
1286 
1287  UIUtilE::Assign(this, m_inetrefEdit, "inetref_edit", &err);
1288  UIUtilW::Assign(this, m_inetrefClear, "inetref_clear", &err);
1289  UIUtilE::Assign(this, m_seasonSpin, "season_spinbox", &err);
1290  UIUtilE::Assign(this, m_episodeSpin, "episode_spinbox", &err);
1291  UIUtilE::Assign(this, m_queryButton, "query_button", &err);
1292  UIUtilE::Assign(this, m_localFanartButton, "local_fanart_button", &err);
1293  UIUtilE::Assign(this, m_localCoverartButton, "local_coverart_button", &err);
1294  UIUtilE::Assign(this, m_localBannerButton, "local_banner_button", &err);
1295  UIUtilE::Assign(this, m_onlineFanartButton, "online_fanart_button", &err);
1296  UIUtilE::Assign(this, m_onlineCoverartButton, "online_coverart_button", &err);
1297  UIUtilE::Assign(this, m_onlineBannerButton, "online_banner_button", &err);
1298  UIUtilW::Assign(this, m_fanart, "fanart");
1299  UIUtilW::Assign(this, m_coverart, "coverart");
1300  UIUtilW::Assign(this, m_banner, "banner");
1301 
1302  if (err)
1303  {
1304  LOG(VB_GENERAL, LOG_ERR, "MetadataOptions, theme is missing "
1305  "required elements");
1306  return false;
1307  }
1308 
1309  connect(m_inetrefClear, SIGNAL(Clicked()),
1310  SLOT(ClearInetref()));
1311  connect(m_queryButton, SIGNAL(Clicked()),
1312  SLOT(PerformQuery()));
1313  connect(m_localFanartButton, SIGNAL(Clicked()),
1314  SLOT(SelectLocalFanart()));
1315  connect(m_localCoverartButton, SIGNAL(Clicked()),
1316  SLOT(SelectLocalCoverart()));
1317  connect(m_localBannerButton, SIGNAL(Clicked()),
1318  SLOT(SelectLocalBanner()));
1319  connect(m_onlineFanartButton, SIGNAL(Clicked()),
1320  SLOT(SelectOnlineFanart()));
1321  connect(m_onlineCoverartButton, SIGNAL(Clicked()),
1322  SLOT(SelectOnlineCoverart()));
1323  connect(m_onlineBannerButton, SIGNAL(Clicked()),
1324  SLOT(SelectOnlineBanner()));
1325 
1326  connect(m_seasonSpin, SIGNAL(itemSelected(MythUIButtonListItem*)),
1327  SLOT(ValuesChanged()));
1328 
1329  // InetRef
1331 
1332  // Season
1333  m_seasonSpin->SetRange(0,9999,1,5);
1335 
1336  // Episode
1337  m_episodeSpin->SetRange(0,9999,1,10);
1339 
1340  if (m_coverart)
1341  {
1343  m_coverart->Load();
1344  }
1345 
1346  if (m_fanart)
1347  {
1349  m_fanart->Load();
1350  }
1351 
1352  if (m_banner)
1353  {
1355  m_banner->Load();
1356  }
1357 
1358  BuildFocusList();
1359 
1360  return true;
1361 }
1362 
1364 {
1365  SetTextFromMaps();
1366 }
1367 
1368 void MetadataOptions::CreateBusyDialog(const QString& title)
1369 {
1370  if (m_busyPopup)
1371  return;
1372 
1373  const QString& message = title;
1374 
1375  m_busyPopup = new MythUIBusyDialog(message, m_popupStack,
1376  "metaoptsdialog");
1377 
1378  if (m_busyPopup->Create())
1380 }
1381 
1383 {
1384  m_recordingRule->m_inetref.clear();
1386 }
1387 
1389 {
1390  CreateBusyDialog(tr("Trying to manually find this "
1391  "recording online..."));
1392 
1394 
1395  lookup->SetAutomatic(false);
1396  m_metadataFactory->Lookup(lookup);
1397 }
1398 
1400 {
1401  QueryComplete(lookup);
1402 }
1403 
1406 {
1407  QString msg = tr("Downloading selected artwork...");
1408  CreateBusyDialog(msg);
1409 
1410  MetadataLookup *lookup = new MetadataLookup();
1411 
1412  lookup->SetType(kMetadataVideo);
1414  lookup->SetAutomatic(true);
1415  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1416 
1417  ArtworkMap downloads;
1418  downloads.insert(type, info);
1419  lookup->SetDownloads(downloads);
1420  lookup->SetAllowOverwrites(true);
1421  lookup->SetTitle(m_recordingRule->m_title);
1423  lookup->SetInetref(m_inetrefEdit->GetText());
1424  lookup->SetSeason(m_seasonSpin->GetIntValue());
1425  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1426 
1427  m_imageDownload->addDownloads(lookup);
1428 }
1429 
1431 {
1432  if (!CanSetArtwork())
1433  return;
1434 
1435  QString url = generate_file_url("Fanart",
1437  "");
1438  FindImagePopup(url,"",*this, "fanart");
1439 }
1440 
1442 {
1443  if (!CanSetArtwork())
1444  return;
1445 
1446  QString url = generate_file_url("Coverart",
1448  "");
1449  FindImagePopup(url,"",*this, "coverart");
1450 }
1451 
1453 {
1454  if (!CanSetArtwork())
1455  return;
1456 
1457  QString url = generate_file_url("Banners",
1459  "");
1460  FindImagePopup(url,"",*this, "banner");
1461 }
1462 
1464 {
1466 }
1467 
1469 {
1471 }
1472 
1474 {
1476 }
1477 
1479 {
1480  // Season
1481  if (m_seasonSpin)
1483 
1484  // Episode
1485  if (m_episodeSpin)
1487 
1488  // InetRef
1489  if (m_inetrefEdit)
1491 }
1492 
1494 {
1495  if (!lookup)
1496  return;
1497 
1498  // InetRef
1499  m_inetrefEdit->SetText(lookup->GetInetref());
1500 
1501  // Season
1502  m_seasonSpin->SetValue(lookup->GetSeason());
1503 
1504  // Episode
1505  m_episodeSpin->SetValue(lookup->GetEpisode());
1506 
1507  InfoMap metadataMap;
1508  lookup->toMap(metadataMap);
1509  SetTextFromMap(metadataMap);
1510 }
1511 
1513  const QString &prefixAlt,
1514  QObject &inst,
1515  const QString &returnEvent)
1516 {
1517  QString fp;
1518 
1519  if (prefix.startsWith("myth://"))
1520  fp = prefix;
1521  else
1522  fp = prefix.isEmpty() ? prefixAlt : prefix;
1523 
1524  MythScreenStack *popupStack =
1525  GetMythMainWindow()->GetStack("popup stack");
1526 
1527  MythUIFileBrowser *fb = new MythUIFileBrowser(popupStack, fp);
1529  if (fb->Create())
1530  {
1531  fb->SetReturnEvent(&inst, returnEvent);
1532  popupStack->AddScreen(fb);
1533  }
1534  else
1535  delete fb;
1536 }
1537 
1539 {
1540  QStringList ret;
1541 
1542  QList<QByteArray> exts = QImageReader::supportedImageFormats();
1543  for (QList<QByteArray>::iterator p = exts.begin(); p != exts.end(); ++p)
1544  {
1545  ret.append(QString("*.").append(*p));
1546  }
1547 
1548  return ret;
1549 }
1550 
1552 {
1553  if (m_inetrefEdit->GetText().isEmpty())
1554  {
1555  ShowOkPopup(tr("You must set a reference number "
1556  "on this rule to set artwork. For items "
1557  "without a metadata source, you can set "
1558  "any unique value."));
1559  return false;
1560  }
1561 
1562  return true;
1563 }
1564 
1566 {
1567  MetadataLookup *lookup = new MetadataLookup();
1568  lookup->SetStep(kLookupSearch);
1569  lookup->SetType(mtype);
1571 
1572  if (type == kUnknownVideo)
1573  {
1575  (m_seasonSpin->GetIntValue() == 0 &&
1576  m_episodeSpin->GetIntValue() == 0))
1577  {
1578  lookup->SetSubtype(kProbableMovie);
1579  }
1580  else
1581  {
1583  }
1584  }
1585  else
1586  {
1587  // we could determine the type from the inetref
1588  lookup->SetSubtype(type);
1589  }
1590  lookup->SetAllowGeneric(true);
1591  lookup->SetHandleImages(false);
1593  lookup->SetTitle(m_recordingRule->m_title);
1595  lookup->SetInetref(m_inetrefEdit->GetText());
1597  lookup->SetSeason(m_seasonSpin->GetIntValue());
1598  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1599 
1600  return lookup;
1601 }
1602 
1604 {
1605  if (!CanSetArtwork())
1606  return;
1607 
1608  QString msg = tr("Searching for available artwork...");
1609  CreateBusyDialog(msg);
1610 
1612 
1613  lookup->SetAutomatic(true);
1614  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1615  m_imageLookup->addLookup(lookup);
1616 }
1617 
1619 {
1620  if (!lookup)
1621  return;
1622 
1623  if (m_busyPopup)
1624  {
1625  m_busyPopup->Close();
1626  m_busyPopup = nullptr;
1627  }
1628 
1629  VideoArtworkType type = lookup->GetData().value<VideoArtworkType>();
1630  ArtworkList list = lookup->GetArtwork(type);
1631 
1632  if (list.isEmpty())
1633  {
1634  MythWarningNotification n(tr("No image found"), tr("Schedule Editor"));
1636  return;
1637  }
1638 
1639  ImageSearchResultsDialog *resultsdialog =
1641 
1642  connect(resultsdialog, SIGNAL(haveResult(ArtworkInfo, VideoArtworkType)),
1644 
1645  if (resultsdialog->Create())
1646  m_popupStack->AddScreen(resultsdialog);
1647 }
1648 
1650 {
1651  if (!lookup)
1652  return;
1653 
1654  DownloadMap map = lookup->GetDownloads();
1655 
1656  if (map.isEmpty())
1657  return;
1658 
1659  for (DownloadMap::const_iterator i = map.begin(); i != map.end(); ++i)
1660  {
1661  VideoArtworkType type = i.key();
1662  const ArtworkInfo& info = i.value();
1663 
1664  if (type == kArtworkCoverart)
1665  m_artworkMap.replace(kArtworkCoverart, info);
1666  else if (type == kArtworkFanart)
1667  m_artworkMap.replace(kArtworkFanart, info);
1668  else if (type == kArtworkBanner)
1669  m_artworkMap.replace(kArtworkBanner, info);
1670  }
1671 
1674 
1675  ValuesChanged();
1676 }
1677 
1679 {
1682 
1683  if (m_coverart)
1684  {
1686  m_coverart->Load();
1687  }
1688 
1689  if (m_fanart)
1690  {
1692  m_fanart->Load();
1693  }
1694 
1695  if (m_banner)
1696  {
1698  m_banner->Load();
1699  }
1700 }
1701 
1702 void MetadataOptions::customEvent(QEvent *levent)
1703 {
1704  if (levent->type() == MetadataFactoryMultiResult::kEventType)
1705  {
1706  if (m_busyPopup)
1707  {
1708  m_busyPopup->Close();
1709  m_busyPopup = nullptr;
1710  }
1711 
1712  MetadataFactoryMultiResult *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
1713 
1714  if (!mfmr)
1715  return;
1716 
1717  MetadataLookupList list = mfmr->m_results;
1718 
1719  if (list.count() > 1)
1720  {
1721  int yearindex = -1;
1722 
1723  for (int p = 0; p != list.size(); ++p)
1724  {
1725  if (!m_recordingRule->m_seriesid.isEmpty() &&
1726  m_recordingRule->m_seriesid == (list[p])->GetTMSref())
1727  {
1728  MetadataLookup *lookup = list[p];
1729  QueryComplete(lookup);
1730  return;
1731  }
1732  if (m_recInfo &&
1734  (list[p])->GetYear() != 0 &&
1735  m_recInfo->GetYearOfInitialRelease() == (list[p])->GetYear())
1736  {
1737  if (yearindex > -1)
1738  {
1739  LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
1740  "match could be found based on year alone.");
1741  yearindex = -2;
1742  }
1743  else if (yearindex == -1)
1744  {
1745  LOG(VB_GENERAL, LOG_INFO, "Matched based on year. ");
1746  yearindex = p;
1747  }
1748  }
1749  }
1750 
1751  if (yearindex > -1)
1752  {
1753  MetadataLookup *lookup = list[yearindex];
1754  QueryComplete(lookup);
1755  return;
1756  }
1757 
1758  LOG(VB_GENERAL, LOG_INFO, "Falling through to selection dialog.");
1759  MetadataResultsDialog *resultsdialog =
1761 
1762  connect(resultsdialog, SIGNAL(haveResult(RefCountHandler<MetadataLookup>)),
1764  Qt::QueuedConnection);
1765 
1766  if (resultsdialog->Create())
1767  m_popupStack->AddScreen(resultsdialog);
1768  }
1769  }
1770  else if (levent->type() == MetadataFactorySingleResult::kEventType)
1771  {
1772  if (m_busyPopup)
1773  {
1774  m_busyPopup->Close();
1775  m_busyPopup = nullptr;
1776  }
1777 
1778  MetadataFactorySingleResult *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
1779 
1780  if (!mfsr)
1781  return;
1782 
1783  MetadataLookup *lookup = mfsr->m_result;
1784 
1785  if (!lookup)
1786  return;
1787 
1788  QueryComplete(lookup);
1789  }
1790  else if (levent->type() == MetadataFactoryNoResult::kEventType)
1791  {
1792  if (m_busyPopup)
1793  {
1794  m_busyPopup->Close();
1795  m_busyPopup = nullptr;
1796  }
1797 
1798  MetadataFactoryNoResult *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
1799 
1800  if (!mfnr)
1801  return;
1802 
1803  QString title = tr("No match found for this recording. You can "
1804  "try entering a TVDB/TMDB number, season, and "
1805  "episode manually.");
1806 
1807  MythConfirmationDialog *okPopup =
1808  new MythConfirmationDialog(m_popupStack, title, false);
1809 
1810  if (okPopup->Create())
1811  m_popupStack->AddScreen(okPopup);
1812  }
1813  else if (levent->type() == MetadataLookupEvent::kEventType)
1814  {
1815  if (m_busyPopup)
1816  {
1817  m_busyPopup->Close();
1818  m_busyPopup = nullptr;
1819  }
1820 
1821  MetadataLookupEvent *lue = (MetadataLookupEvent *)levent;
1822 
1823  MetadataLookupList lul = lue->m_lookupList;
1824 
1825  if (lul.isEmpty())
1826  return;
1827 
1828  if (lul.count() >= 1)
1829  {
1830  OnArtworkSearchDone(lul[0]);
1831  }
1832  }
1833  else if (levent->type() == MetadataLookupFailure::kEventType)
1834  {
1835  if (m_busyPopup)
1836  {
1837  m_busyPopup->Close();
1838  m_busyPopup = nullptr;
1839  }
1840 
1842 
1843  MetadataLookupList lul = luf->m_lookupList;
1844 
1845  if (!lul.empty())
1846  {
1847  QString title = tr("This number, season, and episode combination "
1848  "does not appear to be valid (or the site may "
1849  "be down). Check your information and try "
1850  "again.");
1851 
1852  MythConfirmationDialog *okPopup =
1853  new MythConfirmationDialog(m_popupStack, title, false);
1854 
1855  if (okPopup->Create())
1856  m_popupStack->AddScreen(okPopup);
1857  }
1858  }
1859  else if (levent->type() == ImageDLEvent::kEventType)
1860  {
1861  if (m_busyPopup)
1862  {
1863  m_busyPopup->Close();
1864  m_busyPopup = nullptr;
1865  }
1866 
1867  ImageDLEvent *ide = (ImageDLEvent *)levent;
1868 
1869  MetadataLookup *lookup = ide->m_item;
1870 
1871  if (!lookup)
1872  return;
1873 
1874  HandleDownloadedImages(lookup);
1875  }
1876  else if (levent->type() == ImageDLFailureEvent::kEventType)
1877  {
1878  if (m_busyPopup)
1879  {
1880  m_busyPopup->Close();
1881  m_busyPopup = nullptr;
1882  }
1883  MythErrorNotification n(tr("Failed to retrieve image(s)"),
1884  tr("Schedule Editor"),
1885  tr("Check logs"));
1887  }
1888  else if (levent->type() == DialogCompletionEvent::kEventType)
1889  {
1890  DialogCompletionEvent *dce = (DialogCompletionEvent*)(levent);
1891 
1892  const QString resultid = dce->GetId();
1893  ArtworkInfo info;
1894  info.url = dce->GetResultText();
1895 
1896  if (resultid == "coverart")
1897  {
1898  m_artworkMap.replace(kArtworkCoverart, info);
1899  }
1900  else if (resultid == "fanart")
1901  {
1902  m_artworkMap.replace(kArtworkFanart, info);
1903  }
1904  else if (resultid == "banner")
1905  {
1906  m_artworkMap.replace(kArtworkBanner, info);
1907  }
1908 
1911 
1912  ValuesChanged();
1913  }
1914 
1915 }
1916 
1918 
1925  SchedOptMixin *other)
1926  : m_screen(&screen), m_rule(rule), m_other(other),
1927  m_haveRepeats(gCoreContext->GetBoolSetting("HaveRepeats", false))
1928 {
1929 }
1930 
1931 void SchedOptMixin::Create(bool *err)
1932 {
1933  if (!m_rule)
1934  return;
1935 
1936  if (m_other && !m_other->m_prioritySpin)
1937  UIUtilE::Assign(m_screen, m_prioritySpin, "priority", err);
1938  else
1939  UIUtilW::Assign(m_screen, m_prioritySpin, "priority");
1940 
1942  UIUtilE::Assign(m_screen, m_startoffsetSpin, "startoffset", err);
1943  else
1944  UIUtilW::Assign(m_screen, m_startoffsetSpin, "startoffset");
1945 
1946  if (m_other && !m_other->m_endoffsetSpin)
1947  UIUtilE::Assign(m_screen, m_endoffsetSpin, "endoffset", err);
1948  else
1949  UIUtilW::Assign(m_screen, m_endoffsetSpin, "endoffset");
1950 
1951  if (m_other && !m_other->m_dupmethodList)
1952  UIUtilE::Assign(m_screen, m_dupmethodList, "dupmethod", err);
1953  else
1954  UIUtilW::Assign(m_screen, m_dupmethodList, "dupmethod");
1955 
1956  if (m_other && !m_other->m_dupscopeList)
1957  UIUtilE::Assign(m_screen, m_dupscopeList, "dupscope", err);
1958  else
1959  UIUtilW::Assign(m_screen, m_dupscopeList, "dupscope");
1960 
1961  if (m_other && !m_other->m_inputList)
1962  UIUtilE::Assign(m_screen, m_inputList, "input", err);
1963  else
1965 
1967  UIUtilE::Assign(m_screen, m_ruleactiveCheck, "ruleactive", err);
1968  else
1969  UIUtilW::Assign(m_screen, m_ruleactiveCheck, "ruleactive");
1970 
1971  UIUtilW::Assign(m_screen, m_newrepeatList, "newrepeat");
1972 }
1973 
1975 {
1976  if (!m_rule)
1977  return;
1978 
1979  // Priority
1980  if (m_prioritySpin)
1981  {
1982  if (!m_loaded)
1983  m_prioritySpin->SetRange(-99,99,1,5);
1985  }
1986 
1987  // Start Offset
1988  if (m_startoffsetSpin)
1989  {
1990  if (!m_loaded)
1991  m_startoffsetSpin->SetRange(480,-480,1,10);
1993  }
1994 
1995  // End Offset
1996  if (m_endoffsetSpin)
1997  {
1998  if (!m_loaded)
1999  m_endoffsetSpin->SetRange(-480,480,1,10);
2001  }
2002 
2003  // Duplicate Match Type
2004  if (m_dupmethodList)
2005  {
2006  if (!m_loaded)
2007  {
2009 
2025 
2026  m_rule->m_dupMethod = dupMethod;
2027  }
2029  }
2030 
2031  // Duplicate Matching Scope
2032  if (m_dupscopeList)
2033  {
2034  if (!m_loaded)
2035  {
2045  if (m_haveRepeats && !m_newrepeatList &&
2047  {
2051  }
2052  }
2054  }
2055 
2056  // Preferred Input
2057  if (m_inputList)
2058  {
2059  if (!m_loaded)
2060  {
2062  QObject::tr("Use any available input"),
2063  qVariantFromValue(0));
2064 
2065  vector<uint> inputids = CardUtil::GetSchedInputList();
2066  for (size_t i = 0; i < inputids.size(); ++i)
2067  {
2069  QObject::tr("Prefer input %1")
2070  .arg(CardUtil::GetDisplayName(inputids[i])), inputids[i]);
2071  }
2072  }
2074  }
2075 
2076  // Active/Disabled
2077  if (m_ruleactiveCheck)
2078  {
2080  }
2081 
2082  // Record new and repeat
2083  if (m_newrepeatList)
2084  {
2085  if (!m_loaded)
2086  {
2088  QObject::tr("Record new and repeat "
2089  "episodes"), ENUM_TO_QVARIANT(0));
2091  QObject::tr("Record new episodes only"),
2093  }
2095  (m_rule->m_dupIn & kDupsNewEpi));
2096  }
2097 
2098  m_loaded = true;
2099 
2100  RuleChanged();
2101 }
2102 
2104 {
2105  if (!m_rule)
2106  return;
2107 
2108  if (m_prioritySpin)
2110  if (m_startoffsetSpin)
2112  if (m_endoffsetSpin)
2114  if (m_dupmethodList)
2115  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2116  (m_dupmethodList->GetDataValue().toInt());
2117  if (m_dupscopeList)
2118  {
2119  int mask = ((m_other && m_other->m_newrepeatList) ||
2120  m_newrepeatList) ? kDupsInAll : ~0;
2121  int val = ((m_rule->m_dupIn & ~mask) |
2122  m_dupscopeList->GetDataValue().toInt());
2123  m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2124  }
2125  if (m_inputList)
2127  if (m_ruleactiveCheck)
2129  if (m_newrepeatList)
2130  {
2131  int val = ((m_rule->m_dupIn & ~kDupsNewEpi) |
2132  m_newrepeatList->GetDataValue().toInt());
2133  m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2134  }
2135 }
2136 
2138 {
2139  if (!m_rule)
2140  return;
2141 
2142  bool isScheduled = (m_rule->m_type != kNotRecording &&
2143  m_rule->m_type != kDontRecord);
2144  bool isSingle = (m_rule->m_type == kSingleRecord ||
2146 
2147  if (m_prioritySpin)
2148  m_prioritySpin->SetEnabled(isScheduled);
2149  if (m_startoffsetSpin)
2150  m_startoffsetSpin->SetEnabled(isScheduled);
2151  if (m_endoffsetSpin)
2152  m_endoffsetSpin->SetEnabled(isScheduled);
2153  if (m_dupmethodList)
2154  m_dupmethodList->SetEnabled(isScheduled && !isSingle);
2155  if (m_dupscopeList)
2156  m_dupscopeList->SetEnabled(isScheduled && !isSingle &&
2158  if (m_inputList)
2159  m_inputList->SetEnabled(isScheduled);
2160  if (m_ruleactiveCheck)
2161  m_ruleactiveCheck->SetEnabled(isScheduled);
2162  if (m_newrepeatList)
2163  m_newrepeatList->SetEnabled(isScheduled && !isSingle && m_haveRepeats);
2164 }
2165 
2167 {
2168  if (!item || !m_rule)
2169  return;
2170 
2171  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2172  (item->GetData().toInt());
2173 
2174  if (m_dupscopeList)
2176 }
2177 
2179 
2185 void FilterOptMixin::Create(bool *err)
2186 {
2187  if (!m_rule)
2188  return;
2189 
2190  if (m_other && !m_other->m_filtersList)
2191  UIUtilE::Assign(m_screen, m_filtersList, "filters", err);
2192  else
2193  UIUtilW::Assign(m_screen, m_filtersList, "filters");
2194 
2195  UIUtilW::Assign(m_screen, m_activeFiltersList, "activefilters");
2196  if (m_activeFiltersList)
2198 }
2199 
2201 {
2202  if (!m_rule)
2203  return;
2204 
2205  if (!m_loaded)
2206  {
2207  MSqlQuery query(MSqlQuery::InitCon());
2208 
2209  query.prepare("SELECT filterid, description, newruledefault "
2210  "FROM recordfilter ORDER BY filterid");
2211 
2212  if (query.exec())
2213  {
2214  while (query.next())
2215  {
2216  m_descriptions << QObject::tr(query.value(1).toString()
2217  .toUtf8().constData());
2218  }
2219  }
2220  m_loaded = true;
2221  }
2222 
2223  if (m_activeFiltersList)
2225 
2226  MythUIButtonListItem *button;
2227  QStringList::iterator Idesc;
2228  int idx;
2229  bool not_empty = m_filtersList && !m_filtersList->IsEmpty();
2230  for (Idesc = m_descriptions.begin(), idx = 0;
2231  Idesc != m_descriptions.end(); ++Idesc, ++idx)
2232  {
2233  bool active = (m_rule->m_filter & (1 << idx)) != 0U;
2234  if (m_filtersList)
2235  {
2236  if (not_empty)
2237  button = m_filtersList->GetItemAt(idx);
2238  else
2239  button = new MythUIButtonListItem(m_filtersList, *Idesc, idx);
2240  button->setCheckable(true);
2243  }
2244  if (active && m_activeFiltersList)
2245  {
2246  /* Create a simple list of active filters the theme can
2247  use for informational purposes. */
2249  *Idesc, idx);
2250  button->setCheckable(false);
2251  }
2252  }
2253 
2255  {
2257  QObject::tr("None"), idx);
2258  button->setCheckable(false);
2259  }
2260 
2261  RuleChanged();
2262 }
2263 
2265 {
2266  if (!m_rule || !m_filtersList)
2267  return;
2268 
2269  // Iterate through button list, and build the mask
2270  uint32_t filter_mask = 0;
2271  int idx, end;
2272 
2273  end = m_filtersList->GetCount();
2274  for (idx = 0; idx < end; ++idx)
2275  {
2276  MythUIButtonListItem *button;
2277  if ((button = m_filtersList->GetItemAt(idx)) &&
2279  filter_mask |= (1 << button->GetData().value<uint32_t>());
2280  }
2281  m_rule->m_filter = filter_mask;
2282 }
2283 
2285 {
2286  if (!m_rule)
2287  return;
2288 
2289  bool enabled = m_rule->m_type != kNotRecording &&
2291  if (m_filtersList)
2292  m_filtersList->SetEnabled(enabled);
2293  if (m_activeFiltersList)
2294  m_activeFiltersList->SetEnabled(enabled);
2295 }
2296 
2298 {
2302 }
2303 
2304 
2306 
2312 void StoreOptMixin::Create(bool *err)
2313 {
2314  if (!m_rule)
2315  return;
2316 
2317  if (m_other && !m_other->m_recprofileList)
2318  UIUtilE::Assign(m_screen, m_recprofileList, "recprofile", err);
2319  else
2320  UIUtilW::Assign(m_screen, m_recprofileList, "recprofile");
2321 
2322  if (m_other && !m_other->m_recgroupList)
2323  UIUtilE::Assign(m_screen, m_recgroupList, "recgroup", err);
2324  else
2325  UIUtilW::Assign(m_screen, m_recgroupList, "recgroup");
2326 
2328  UIUtilE::Assign(m_screen, m_storagegroupList, "storagegroup", err);
2329  else
2330  UIUtilW::Assign(m_screen, m_storagegroupList, "storagegroup");
2331 
2332  if (m_other && !m_other->m_playgroupList)
2333  UIUtilE::Assign(m_screen, m_playgroupList, "playgroup", err);
2334  else
2335  UIUtilW::Assign(m_screen, m_playgroupList, "playgroup");
2336 
2337  if (m_other && !m_other->m_maxepSpin)
2338  UIUtilE::Assign(m_screen, m_maxepSpin, "maxepisodes", err);
2339  else
2340  UIUtilW::Assign(m_screen, m_maxepSpin, "maxepisodes");
2341 
2343  UIUtilE::Assign(m_screen, m_maxbehaviourList, "maxnewest", err);
2344  else
2346 
2348  UIUtilE::Assign(m_screen, m_autoexpireCheck, "autoexpire", err);
2349  else
2350  UIUtilW::Assign(m_screen, m_autoexpireCheck, "autoexpire");
2351 }
2352 
2354 {
2355  if (!m_rule)
2356  return;
2357 
2358  QString label;
2359  QStringList groups;
2360  QStringList::Iterator it;
2361  MSqlQuery query(MSqlQuery::InitCon());
2362 
2363  // Recording Profile
2364  if (m_recprofileList)
2365  {
2366  if (!m_loaded)
2367  {
2368  label = QObject::tr("Record using the %1 profile");
2369 
2371  label.arg(QObject::tr("Default")),
2372  qVariantFromValue(QString("Default")));
2373  // LiveTV profile - it's for LiveTV not scheduled recordings??
2375  label.arg(QObject::tr("LiveTV")),
2376  qVariantFromValue(QString("LiveTV")));
2378  label.arg(QObject::tr("High Quality")),
2379  qVariantFromValue(QString("High Quality")));
2381  label.arg(QObject::tr("Low Quality")),
2382  qVariantFromValue(QString("Low Quality")));
2383  }
2385  }
2386 
2387  // Recording Group
2388  if (m_recgroupList)
2389  {
2390  if (!m_loaded)
2391  {
2392  label = QObject::tr("Include in the \"%1\" recording group");
2394  QObject::tr("Create a new recording group"),
2395  qVariantFromValue(QString("__NEW_GROUP__")));
2396 
2397  query.prepare("SELECT recgroupid, recgroup FROM recgroups "
2398  "WHERE recgroup <> 'Deleted' AND "
2399  " recgroup <> 'LiveTV' "
2400  "ORDER BY special DESC, recgroup ASC"); // Special groups first
2401  if (query.exec())
2402  {
2403  while (query.next())
2404  {
2405  int id = query.value(0).toInt();
2406  QString name = query.value(1).toString();
2407 
2408  if (name == "Default")
2409  name = QObject::tr("Default");
2410  new MythUIButtonListItem(m_recgroupList, label.arg(name),
2411  qVariantFromValue(id));
2412  }
2413  }
2414 
2415  }
2417  }
2418 
2419  // Storage Group
2420  if (m_storagegroupList)
2421  {
2422  if (!m_loaded)
2423  {
2424  label = QObject::tr("Store in the \"%1\" storage group");
2426  label.arg(QObject::tr("Default")),
2427  qVariantFromValue(QString("Default")));
2428 
2430  for (it = groups.begin(); it != groups.end(); ++it)
2431  {
2432  if ((*it).compare("Default", Qt::CaseInsensitive) != 0)
2434  label.arg(*it), qVariantFromValue(*it));
2435  }
2436  }
2438  }
2439 
2440  // Playback Group
2441  if (m_playgroupList)
2442  {
2443  if (!m_loaded)
2444  {
2445  label = QObject::tr("Use \"%1\" playback group settings");
2447  label.arg(QObject::tr("Default")),
2448  qVariantFromValue(QString("Default")));
2449 
2450  groups = PlayGroup::GetNames();
2451  for (it = groups.begin(); it != groups.end(); ++it)
2452  {
2453  new MythUIButtonListItem(m_playgroupList, label.arg(*it),
2454  qVariantFromValue(*it));
2455  }
2456  }
2458  }
2459 
2460  // Max Episodes
2461  if (m_maxepSpin)
2462  {
2463  if (!m_loaded)
2464  {
2465  int maxEpisodes = m_rule->m_maxEpisodes;
2466  m_maxepSpin->SetRange(0,100,1,5);
2467  m_rule->m_maxEpisodes = maxEpisodes;
2468  }
2470  }
2471 
2472  // Max Episode Behaviour
2473  if (m_maxbehaviourList)
2474  {
2475  if (!m_loaded)
2476  {
2478  QObject::tr("Don't record if this would exceed the max "
2479  "episodes"), qVariantFromValue(false));
2481  QObject::tr("Delete oldest if this would exceed the max "
2482  "episodes"), qVariantFromValue(true));
2483  }
2485  }
2486 
2487  // Auto-Expire
2488  if (m_autoexpireCheck)
2489  {
2491  }
2492 
2493  m_loaded = true;
2494 
2495  RuleChanged();
2496 }
2497 
2499 {
2500  if (!m_rule)
2501  return;
2502 
2503  if (m_recprofileList)
2505 
2506  if (m_recgroupList)
2507  {
2508  // If the user selected 'Create a new regroup' but failed to enter a
2509  // name when prompted, restore the original value
2510  if (m_recgroupList->GetDataValue().toString() == "__NEW_GROUP__")
2513  }
2514 
2515  if (m_storagegroupList)
2517 
2518  if (m_playgroupList)
2520 
2521  if (m_maxepSpin)
2523 
2524  if (m_maxbehaviourList)
2526 
2527  if (m_autoexpireCheck)
2529 }
2530 
2532 {
2533  if (!m_rule)
2534  return;
2535 
2536  bool isScheduled = (m_rule->m_type != kNotRecording &&
2537  m_rule->m_type != kDontRecord);
2538  bool isSingle = (m_rule->m_type == kSingleRecord ||
2540 
2541  if (m_recprofileList)
2542  m_recprofileList->SetEnabled(isScheduled);
2543  if (m_recgroupList)
2544  m_recgroupList->SetEnabled(isScheduled);
2545  if (m_storagegroupList)
2546  m_storagegroupList->SetEnabled(isScheduled);
2547  if (m_playgroupList)
2548  m_playgroupList->SetEnabled(isScheduled);
2549  if (m_maxepSpin)
2550  m_maxepSpin->SetEnabled(isScheduled && !isSingle);
2551  if (m_maxbehaviourList)
2552  m_maxbehaviourList->SetEnabled(isScheduled && !isSingle &&
2553  m_rule->m_maxEpisodes != 0);
2554  if (m_autoexpireCheck)
2555  m_autoexpireCheck->SetEnabled(isScheduled);
2556 }
2557 
2559 {
2560  if (!item || !m_rule)
2561  return;
2562 
2563  m_rule->m_maxEpisodes = item->GetData().toInt();
2564 
2565  if (m_maxbehaviourList)
2567 }
2568 
2570 {
2571  if (!m_rule)
2572  return;
2573 
2574  if (m_recgroupList->GetDataValue().toString() != "__NEW_GROUP__")
2575  return;
2576 
2577  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2578 
2579  QString label =
2580  QObject::tr("New Recording group name: ");
2581 
2582  MythTextInputDialog *textDialog =
2583  new MythTextInputDialog(popupStack, label,
2584  static_cast<InputFilter>(FilterSymbols | FilterPunct));
2585 
2586  textDialog->SetReturnEvent(m_screen, "newrecgroup");
2587 
2588  if (textDialog->Create())
2589  popupStack->AddScreen(textDialog, false);
2590 }
2591 
2592 void StoreOptMixin::SetRecGroup(int recgroupID, QString recgroup)
2593 {
2594  if (!m_rule || recgroupID <= 0)
2595  return;
2596 
2597  if (m_recgroupList)
2598  {
2599  recgroup = recgroup.trimmed();
2600  if (recgroup.isEmpty())
2601  return;
2602 
2603  QString label = QObject::tr("Include in the \"%1\" recording group");
2604  MythUIButtonListItem *item =
2605  new MythUIButtonListItem(m_recgroupList, label.arg(recgroup),
2606  qVariantFromValue(recgroup));
2608 
2609  if (m_other && m_other->m_recgroupList)
2610  {
2612  label.arg(recgroup), qVariantFromValue(recgroupID));
2614  }
2615  }
2616 }
2617 
2618 int StoreOptMixin::CreateRecordingGroup(const QString& groupName)
2619 {
2620  int groupID = -1;
2621  MSqlQuery query(MSqlQuery::InitCon());
2622 
2623  query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
2624  "displayname = :DISPLAYNAME");
2625  query.bindValue(":NAME", groupName);
2626  query.bindValue(":DISPLAYNAME", groupName);
2627 
2628  if (query.exec())
2629  groupID = query.lastInsertId().toInt();
2630 
2631  if (groupID <= 0)
2632  LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
2633  "Does it already exist?").arg(groupName));
2634 
2635  return groupID;
2636 }
2637 
2639 
2645 void PostProcMixin::Create(bool *err)
2646 {
2647  if (!m_rule)
2648  return;
2649 
2650  if (m_other && !m_other->m_commflagCheck)
2651  UIUtilE::Assign(m_screen, m_commflagCheck, "autocommflag", err);
2652  else
2653  UIUtilW::Assign(m_screen, m_commflagCheck, "autocommflag");
2654 
2655  if (m_other && !m_other->m_transcodeCheck)
2656  UIUtilE::Assign(m_screen, m_transcodeCheck, "autotranscode", err);
2657  else
2658  UIUtilW::Assign(m_screen, m_transcodeCheck, "autotranscode");
2659 
2661  UIUtilE::Assign(m_screen, m_transcodeprofileList, "transcodeprofile", err);
2662  else
2663  UIUtilW::Assign(m_screen, m_transcodeprofileList, "transcodeprofile");
2664 
2665  if (m_other && !m_other->m_userjob1Check)
2666  UIUtilE::Assign(m_screen, m_userjob1Check, "userjob1", err);
2667  else
2669 
2670  if (m_other && !m_other->m_userjob2Check)
2671  UIUtilE::Assign(m_screen, m_userjob2Check, "userjob2", err);
2672  else
2674 
2675  if (m_other && !m_other->m_userjob3Check)
2676  UIUtilE::Assign(m_screen, m_userjob3Check, "userjob3", err);
2677  else
2679 
2680  if (m_other && !m_other->m_userjob4Check)
2681  UIUtilE::Assign(m_screen, m_userjob4Check, "userjob4", err);
2682  else
2684 
2685  UIUtilW::Assign(m_screen, m_metadataLookupCheck, "metadatalookup");
2686 }
2687 
2689 {
2690  if (!m_rule)
2691  return;
2692 
2693  // Auto-commflag
2694  if (m_commflagCheck)
2695  {
2697  }
2698 
2699  // Auto-transcode
2700  if (m_transcodeCheck)
2701  {
2703  }
2704 
2705  // Transcode Method
2707  {
2708  if (!m_loaded)
2709  {
2710  QMap<int, QString> profiles = RecordingProfile::GetTranscodingProfiles();
2711  QMap<int, QString>::iterator it;
2712  for (it = profiles.begin(); it != profiles.end(); ++it)
2713  {
2715  qVariantFromValue(it.key()));
2716  }
2717  }
2719  }
2720 
2721  // User Job #1
2722  if (m_userjob1Check)
2723  {
2724  if (!m_loaded)
2725  {
2726  MythUIText *userjob1Text = nullptr;
2727  UIUtilW::Assign(m_screen, userjob1Text, "userjob1text");
2728  if (userjob1Text)
2729  userjob1Text->SetText(QObject::tr("Run '%1'")
2730  .arg(gCoreContext->GetSetting("UserJobDesc1", "User Job 1")));
2731  }
2733  }
2734 
2735  // User Job #2
2736  if (m_userjob2Check)
2737  {
2738  if (!m_loaded)
2739  {
2740  MythUIText *userjob2Text = nullptr;
2741  UIUtilW::Assign(m_screen, userjob2Text, "userjob2text");
2742  if (userjob2Text)
2743  userjob2Text->SetText(QObject::tr("Run '%1'")
2744  .arg(gCoreContext->GetSetting("UserJobDesc2", "User Job 2")));
2745  }
2747  }
2748 
2749  // User Job #3
2750  if (m_userjob3Check)
2751  {
2752  if (!m_loaded)
2753  {
2754  MythUIText *userjob3Text = nullptr;
2755  UIUtilW::Assign(m_screen, userjob3Text, "userjob3text");
2756  if (userjob3Text)
2757  userjob3Text->SetText(QObject::tr("Run '%1'")
2758  .arg(gCoreContext->GetSetting("UserJobDesc3", "User Job 3")));
2759  }
2761  }
2762 
2763  // User Job #4
2764  if (m_userjob4Check)
2765  {
2766  if (!m_loaded)
2767  {
2768  MythUIText *userjob4Text = nullptr;
2769  UIUtilW::Assign(m_screen, userjob4Text, "userjob4text");
2770  if (userjob4Text)
2771  userjob4Text->SetText(QObject::tr("Run '%1'")
2772  .arg(gCoreContext->GetSetting("UserJobDesc4", "User Job 4")));
2773  }
2775  }
2776 
2777  // Auto Metadata Lookup
2779  {
2781  }
2782 
2783  m_loaded = true;
2784 
2785  RuleChanged();
2786 }
2787 
2789 {
2790  if (!m_rule)
2791  return;
2792 
2793  if (m_commflagCheck)
2795  if (m_transcodeCheck)
2799  if (m_userjob1Check)
2801  if (m_userjob2Check)
2803  if (m_userjob3Check)
2805  if (m_userjob4Check)
2810 }
2811 
2813 {
2814  if (!m_rule)
2815  return;
2816 
2817  bool isScheduled = (m_rule->m_type != kNotRecording &&
2818  m_rule->m_type != kDontRecord);
2819 
2820  if (m_commflagCheck)
2821  m_commflagCheck->SetEnabled(isScheduled);
2822  if (m_transcodeCheck)
2823  m_transcodeCheck->SetEnabled(isScheduled);
2825  m_transcodeprofileList->SetEnabled(isScheduled &&
2827  if (m_userjob1Check)
2828  m_userjob1Check->SetEnabled(isScheduled);
2829  if (m_userjob2Check)
2830  m_userjob2Check->SetEnabled(isScheduled);
2831  if (m_userjob3Check)
2832  m_userjob3Check->SetEnabled(isScheduled);
2833  if (m_userjob4Check)
2834  m_userjob4Check->SetEnabled(isScheduled);
2836  m_metadataLookupCheck->SetEnabled(isScheduled);
2837 }
2838 
2840 {
2841  if (!m_rule)
2842  return;
2843 
2844  m_rule->m_autoTranscode = enable;
2845 
2848 }
QString m_subtitle
Definition: recordingrule.h:81
MetadataFactory * m_metadataFactory
MythScreenType * m_screen
void Create(bool *err)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:782
void Save(void) override
MythUICheckBox * m_commflagCheck
bool m_isInactive
Recording rule is enabled?
Definition: recordingrule.h:76
void SetTitle(const QString &title)
void SetHandleImages(bool handle)
void MaxEpisodesChanged(MythUIButtonListItem *)
static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"))
MythScreenStack * GetScreenStack() const
ScheduleEditor(MythScreenStack *parent, RecordingInfo *recinfo, TV *player=nullptr)
Select post-processing options.
void ruleDeleted(int ruleId)
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
void showUpcomingByTitle(void)
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:863
void Save(void) override
static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"))
ArtworkList GetArtwork(VideoArtworkType type) const
MythUICheckBox * m_ruleactiveCheck
void RuleChanged(void)
void DupMethodChanged(MythUIButtonListItem *)
void SetSubtitle(const QString &subtitle)
void SetAutomatic(bool autom)
#define ENUM_TO_QVARIANT(a)
MythUISpinBox * m_endoffsetSpin
bool StartEmbedding(const QRect &)
Definition: tv_play.cpp:8534
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
QString toDescription(RecordingType rectype)
Converts "rectype" into a human readable description.
bool LoadByProgram(const ProgramInfo *proginfo)
MythUIButton * m_localFanartButton
Dialog asking for user confirmation.
Select schedule filters.
void ToggleSelected(MythUIButtonListItem *item)
bool Create(void) override
void LosingFocus()
void SetEnabled(bool enable)
Select artwork and inetref for recordings.
bool Delete(bool sendSig=true)
void TranscodeChanged(bool enable)
RecordingRule * m_recordingRule
MythScreenType * m_screen
MythUIButtonList * m_filtersList
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
void showUpcomingByRule(void)
All purpose text widget, displays a text string.
Definition: mythuitext.h:28
static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor", "This time"))
MetadataType
void Load(void) override
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
ArtworkMap m_artworkMap
MythUISpinBox * m_prioritySpin
PostProcEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
void ToMap(InfoMap &infoMap) const
void templateLoaded(void)
void SetInetref(const QString &inetref)
void FindImagePopup(const QString &prefix, const QString &prefixAlt, QObject &inst, const QString &returnEvent)
void SetData(QVariant data)
void MaxEpisodesChanged(MythUIButtonListItem *)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
bool Create(void) override
Definition: proglist.cpp:98
void SetAllowOverwrites(bool allow)
MythUIButtonList * m_playgroupList
void TranscodeChanged(bool enable)
LookupType GuessLookupType(ProgramInfo *pginfo)
Basic menu dialog, message and a list of options.
void SetRule(RecordingRule *rule)
void Create(bool *err)
void SetReturnEvent(QObject *retobject, const QString &resultid)
VideoArtworkType
static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor", "This day and time"))
MythUICheckBox * m_userjob4Check
MythUIButton * m_filtersButton
QString m_storageGroup
void customEvent(QEvent *event) override
static QStringList getRecordingsGroups(void)
bool SetArtwork(const QString &inetref, uint season, const QString &host, const QString &coverart, const QString &fanart, const QString &banner)
QString m_station
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:136
bool Create(void) override
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:34
void ToggleSelected(MythUIButtonListItem *item)
MythScreenStack * GetStack(const QString &stackname)
static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"))
int m_recordID
Unique Recording Rule ID.
Definition: recordingrule.h:72
RecordingInfo * m_recInfo
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void SetValue(int val) override
Definition: mythuispinbox.h:26
RecordingType m_type
MythScreenStack * GetMainStack()
MythUIButton * m_schedOptButton
virtual void ShowDetails(void) const
Show the Program Details screen.
void showTemplateMenu(void)
SchedEditChild * m_child
RecordingDupMethodType m_dupMethod
void ShowSchedInfo(void)
MythUIButtonListItem * GetItemAt(int pos) const
Select schedule options.
static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"))
static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"))
void OnImageSearchListSelection(const ArtworkInfo &info, VideoArtworkType type)
void SetRule(RecordingRule *rule)
SchedEditChild(MythScreenStack *parent, const QString &name, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
MythUITextEdit * m_inetrefEdit
void DeleteRule(void)
bool Create(void) override
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
Mixin for schedule options.
static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor", "This channel"))
void BuildFocusList(void)
void Load(void) override
static Type kEventType
Definition: mythdialogbox.h:50
RecordingRule * m_recordingRule
MetadataLookup * CreateLookup(MetadataType mtype)
MythUICheckBox * m_metadataLookupCheck
int GetIntValue(void) const override
Definition: mythuispinbox.h:33
MythUIImage * m_fanart
uint GetSeason() const
MetadataLookupList m_results
void SetStep(LookupStep step)
RecordingDupMethodType
void SetNameFilter(QStringList filter)
QVariant value(int i) const
Definition: mythdbcon.h:198
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
void MaxEpisodesChanged(MythUIButtonListItem *)
virtual void Close()
MythUIButton * m_cancelButton
void setCheckable(bool flag)
MythScreenType * m_screen
MythUIButton * m_onlineFanartButton
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
bool Save(bool sendSig=true)
uint GetEpisode() const
Holds information on recordings and videos.
Definition: programinfo.h:66
void SetRange(int low, int high, int step, uint pageMultiple=5)
Set the lower and upper bounds of the spinbox, the interval and page amount.
bool Create(void) override
RecordingRule * m_rule
void OnArtworkSearchDone(MetadataLookup *lookup)
bool GetBooleanCheckState(void) const
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Select storage options.
void toMap(InfoMap &map)
MythUIButton * m_metadataButton
MythUIButton * m_inetrefClear
void Load(void) override
MythUICheckBox * m_transcodeCheck
This class is used as a container for messages.
Definition: mythevent.h:16
void DupMethodChanged(MythUIButtonListItem *)
MythUIButton * m_saveButton
RecordingRule * m_rule
virtual void ShowGuide(void) const
Show the program guide.
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
MythUIButtonList * m_storagegroupList
void FilterChanged(MythUIButtonListItem *)
bool Create(void) override
void ruleSaved(int ruleId)
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:887
static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"))
Mixin for Filters.
MythUIButton * m_filtersButton
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
MythUIImage * m_coverart
bool Create(void) override
void SetAllowGeneric(bool allow)
MetadataLookupList m_lookupList
Construct a recording schedule.
bool m_autoMetadataLookup
QString GetSetting(const QString &key, const QString &defaultval="")
void RuleChanged(void)
MythUICheckBox * m_autoexpireCheck
void SetReturnEvent(QObject *retobject, const QString &resultid)
void addDownloads(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_downloadList takes ownership of the ...
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
QString m_playGroup
void Create(bool *err)
MythUIButtonList * m_inputList
MythUIButton * m_backButton
static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"))
void ShowPostProc(void)
void customEvent(QEvent *event) override
StoreOptEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
MythUIButton * m_schedInfoButton
virtual void SetTextFromMap(const InfoMap &infoMap)
Control TV playback.
Definition: tv_play.h:284
QString GetMasterHostName(void)
RecordingRule * m_rule
QVariant GetDataValue() const
MythUIButton * m_saveButton
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
bool LoadTemplate(const QString &category, const QString &categoryType="Default")
virtual bool CreateEditChild(const QString &xmlfile, const QString &winname, bool isTemplate)
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
Mixin for storage options.
void SetRule(RecordingRule *rule)
static vector< uint > GetSchedInputList(void)
void Closing(void)
bool Create(void) override
uint GetSeason(void) const
Definition: programinfo.h:358
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
void FindNetArt(VideoArtworkType type)
void Save(void) override
void CreateBusyDialog(const QString &title)
MythUIBusyDialog * m_busyPopup
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:32
void SetDownloads(ArtworkMap map)
void SetRecGroup(int recgroupID, QString recgroup)
QString GetInetref() const
bool Create(void) override
const char * name
Definition: ParseText.cpp:328
MetadataLookup * m_item
void ShowSchedOpt(void)
void ShowFilters(void)
FilterOptMixin * m_other
void ShowMetadataOptions(void)
QString m_seriesid
Definition: recordingrule.h:93
void Save(void) override
MythUIButton * m_localBannerButton
MythUIButton * m_previewButton
CheckState state() const
void SetSeason(uint season)
RecordingRule * m_rule
MythUIButtonList * m_newrepeatList
RecordingInfo * m_recInfo
bool Create(void) override
void PromptForRecGroup(void)
MythUIButton * m_postProcButton
void SetCollectionref(const QString &collectionref)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
RecordingDupInType m_dupIn
void ChildClosing(void)
void SetText(const QString &text, bool moveCursor=true)
QVariant GetData() const
MythUIType * GetFocusWidget(void) const
QString m_inetref
Definition: recordingrule.h:96
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
void Create(bool *err)
QStringList GetSupportedImageExtensionFilter()
MythScreenType * m_screen
QList< ArtworkInfo > ArtworkList
MythUIImage * m_banner
MetadataDownload * m_imageLookup
uint GetYearOfInitialRelease(void) const
Definition: programinfo.h:415
void PromptForRecGroup(void)
MythUISpinBox * m_startoffsetSpin
void Load(void) override
MythUISpinBox * m_seasonSpin
MythUIButton * m_onlineBannerButton
MythUIButtonList * m_transcodeprofileList
static QString fs11(QT_TRANSLATE_NOOP("SchedFilterEditor", "No episodes"))
Dialog prompting the user to enter a text string.
void TranscodeChanged(bool enable)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:807
void DupMethodChanged(MythUIButtonListItem *item)
MythUICheckBox * m_userjob3Check
QMap< VideoArtworkType, ArtworkInfo > DownloadMap
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static Type kEventType
bool IsLoaded() const
Definition: recordingrule.h:57
void QueryComplete(MetadataLookup *lookup)
QString m_title
Definition: recordingrule.h:79
void SetHost(const QString &host)
void RuleChanged(void)
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
void ShowStoreOpt(void)
bool Create(void) override
MythUIButton * m_onlineCoverartButton
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
SchedOptMixin(MythScreenType &screen, RecordingRule *rule, SchedOptMixin *other=nullptr)
void SetReturnEvent(QObject *retobject, const QString &resultid)
void showMenu(void)
MythUICheckBox * m_userjob2Check
void Lookup(ProgramInfo *pginfo, bool automatic=true, bool getimages=true, bool allowgeneric=false)
void SetSubtype(LookupType subtype)
MythUIButtonList * m_maxbehaviourList
QString m_recProfile
uint GetRecordingRuleID(void) const
Definition: programinfo.h:441
void SetRule(RecordingRule *rule)
void UseTempTable(bool usetemp, const QString &table="record_tmp")
MythUIButton * m_previewButton
QStringList m_descriptions
MythScreenStack * m_popupStack
bool CanSetArtwork(void)
static QStringList GetNames(void)
Definition: playgroup.cpp:206
SchedFilterEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
void SetCheckState(MythUIStateType::StateType state)
MythUIButtonList * m_dupscopeList
bool Load(bool asTemplate=false)
Load a single rule from the recorded table.
void SetType(MetadataType type)
unsigned m_filter
QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
Definition: videoutils.h:65
void Close(void) override
QString m_category
Definition: recordingrule.h:86
MythUICheckBox * m_userjob1Check
void Load(void) override=0
void LoadTemplate(QString name)
void SetItemCurrent(MythUIButtonListItem *item)
MythUIButton * m_queryButton
DownloadMap GetDownloads() const
void Load(void) override
MetadataImageDownload * m_imageDownload
MythUIButton * m_localCoverartButton
static QStringList GetTemplateNames(void)
void PromptForRecGroup(void)
MetadataLookupList m_lookupList
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
MythUIButtonList * m_dupmethodList
void SetEpisode(uint episode)
Screen in which all other widgets are contained and rendered.
void Save(void) override
MythUISpinBox * m_maxepSpin
ScheduleEditor * m_editor
MythUIButtonList * m_activeFiltersList
void addLookup(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_lookupList takes ownership of the gi...
MythUISpinBox * m_episodeSpin
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
virtual void Save(void)=0
LookupType
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
void ShowNextView(void)
MythUIButton * m_storeOptButton
static void * RunScheduleEditor(ProgramInfo *proginfo, void *player=nullptr)
Callback.
StoreOptMixin * m_other
static QMap< int, QString > GetTranscodingProfiles()
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:344
void ShowPreviousView(void)
void OnSearchListSelection(const RefCountHandler< MetadataLookup > &lookup)
MythUIButtonList * m_recprofileList
CategoryType GetCategoryType(void) const
Definition: programinfo.h:430
static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"))
MetadataOptions(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
PostProcMixin * m_other
void setChecked(CheckState state)
int CreateRecordingGroup(const QString &groupName)
SchedOptMixin * m_other
MythUIButtonList * m_recgroupList
void ShowPreview(void)
RecSearchType m_searchType
Mixin for post processing.
ArtworkMap GetArtwork(const QString &inetref, uint season, bool strict)
QString GetText(void) const
MythNotificationCenter * GetNotificationCenter(void)
MythUIButtonListItem * GetItemCurrent() const
void SetValueByData(const QVariant &data)
bool Create(void) override
MythUIButtonList * m_rulesList
uint GetEpisode(void) const
Definition: programinfo.h:359
void Close(void) override
SchedOptEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
void SetTextFromMaps(void)
bool Create(void) override
void RuleChanged(void)
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1706
void customEvent(QEvent *event) override
void HandleDownloadedImages(MetadataLookup *lookup)