MythTV  master
scheduleeditor.cpp
Go to the documentation of this file.
1 
2 #include "scheduleeditor.h"
3 
4 // QT
5 #include <QString>
6 #include <QHash>
7 #include <QCoreApplication>
8 
9 // Libmyth
10 #include "mythcorecontext.h"
11 #include "storagegroup.h"
12 #include "programtypes.h"
13 #include "recordingtypes.h"
14 
15 // Libmythtv
16 #include "playgroup.h"
17 #include "tv_play.h"
18 #include "recordingprofile.h"
19 #include "cardutil.h"
20 
21 // Libmythui
22 #include "mythmainwindow.h"
23 #include "mythuihelper.h"
24 #include "mythuibuttonlist.h"
25 #include "mythuibutton.h"
26 #include "mythuitext.h"
27 #include "mythuiimage.h"
28 #include "mythuistatetype.h"
29 #include "mythuispinbox.h"
30 #include "mythuicheckbox.h"
31 #include "mythdialogbox.h"
32 #include "mythprogressdialog.h"
33 #include "mythuifilebrowser.h"
34 #include "mythuimetadataresults.h"
35 #include "mythuiimageresults.h"
36 #include "videoutils.h"
37 #include "mythuiutils.h"
38 #include "mythtypes.h"
39 
40 #include "metadataimagehelper.h"
41 
42 // Mythfrontend
43 #include "proglist.h"
44 #include "viewschedulediff.h"
45 
46 #define ENUM_TO_QVARIANT(a) qVariantFromValue(static_cast<int>(a))
47 
48 //static const QString _Location = QObject::tr("Schedule Editor");
49 
50 // Define the strings inserted into the recordfilter table in the
51 // database. This should make them available to the translators.
52 static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"));
53 static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"));
54 static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"));
55 static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"));
56 static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"));
57 static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"));
58 static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"));
59 static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"));
60 static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor", "This time"));
61 static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor", "This day and time"));
62 static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor", "This channel"));
63 static QString fs11(QT_TRANSLATE_NOOP("SchedFilterEditor", "No episodes"));
64 
65 void *ScheduleEditor::RunScheduleEditor(ProgramInfo *proginfo, void *player)
66 {
67  RecordingRule *rule = new RecordingRule();
68  rule->LoadByProgram(proginfo);
69 
71  ScheduleEditor *se = new ScheduleEditor(mainStack, rule,
72  static_cast<TV*>(player));
73 
74  if (se->Create())
75  mainStack->AddScreen(se, (player == nullptr));
76  else
77  delete se;
78 
79  return nullptr;
80 }
81 
88  RecordingInfo *recInfo, TV *player)
89  : ScheduleCommon(parent, "ScheduleEditor"),
90  SchedOptMixin(*this, nullptr), FilterOptMixin(*this, nullptr),
91  StoreOptMixin(*this, nullptr), PostProcMixin(*this, nullptr),
92  m_recInfo(new RecordingInfo(*recInfo)), m_recordingRule(nullptr),
93  m_sendSig(false),
94  m_saveButton(nullptr), m_cancelButton(nullptr), m_rulesList(nullptr),
95  m_schedOptButton(nullptr), m_storeOptButton(nullptr),
96  m_postProcButton(nullptr), m_schedInfoButton(nullptr),
97  m_previewButton(nullptr), m_metadataButton(nullptr),
98  m_filtersButton(nullptr),
99  m_player(player), m_loaded(false), m_view(kMainView), m_child(nullptr)
100 {
107 }
108 
110  RecordingRule *recRule, TV *player)
111  : ScheduleCommon(parent, "ScheduleEditor"),
112  SchedOptMixin(*this, recRule),
113  FilterOptMixin(*this, recRule),
114  StoreOptMixin(*this, recRule),
115  PostProcMixin(*this, recRule),
116  m_recInfo(nullptr), m_recordingRule(recRule),
117  m_sendSig(false),
118  m_saveButton(nullptr), m_cancelButton(nullptr), m_rulesList(nullptr),
119  m_schedOptButton(nullptr), m_storeOptButton(nullptr),
120  m_postProcButton(nullptr), m_schedInfoButton(nullptr),
121  m_previewButton(nullptr), m_metadataButton(nullptr),
122  m_filtersButton(nullptr),
123  m_player(player), m_loaded(false), m_view(kMainView), m_child(nullptr)
124 {
125 }
126 
128 {
129  delete m_recordingRule;
130 
131  // if we have a player, we need to tell we are done
132  if (m_player)
133  {
134  QString message = QString("VIEWSCHEDULED_EXITING");
135  qApp->postEvent(m_player, new MythEvent(message));
136  }
137 }
138 
140 {
141  if (!LoadWindowFromXML("schedule-ui.xml", "scheduleeditor", this))
142  return false;
143 
144  bool err = false;
145 
146  UIUtilE::Assign(this, m_rulesList, "rules", &err);
147 
148  UIUtilW::Assign(this, m_schedOptButton, "schedoptions");
149  UIUtilW::Assign(this, m_storeOptButton, "storeoptions");
150  UIUtilW::Assign(this, m_postProcButton, "postprocessing");
151  UIUtilW::Assign(this, m_metadataButton, "metadata");
152  UIUtilW::Assign(this, m_schedInfoButton, "schedinfo");
153  UIUtilW::Assign(this, m_previewButton, "preview");
154  UIUtilW::Assign(this, m_filtersButton, "filters");
155 
156  SchedOptMixin::Create(&err);
158  StoreOptMixin::Create(&err);
159  PostProcMixin::Create(&err);
160 
161  UIUtilW::Assign(this, m_cancelButton, "cancel");
162  UIUtilE::Assign(this, m_saveButton, "save", &err);
163 
164  if (err)
165  {
166  LOG(VB_GENERAL, LOG_ERR, "ScheduleEditor, theme is missing "
167  "required elements");
168  return false;
169  }
170 
171  connect(m_rulesList, SIGNAL(itemSelected(MythUIButtonListItem *)),
173 
174  if (m_schedOptButton)
175  connect(m_schedOptButton, SIGNAL(Clicked()), SLOT(ShowSchedOpt()));
176  if (m_filtersButton)
177  connect(m_filtersButton, SIGNAL(Clicked()), SLOT(ShowFilters()));
178  if (m_storeOptButton)
179  connect(m_storeOptButton, SIGNAL(Clicked()), SLOT(ShowStoreOpt()));
180  if (m_postProcButton)
181  connect(m_postProcButton, SIGNAL(Clicked()), SLOT(ShowPostProc()));
182  if (m_schedInfoButton)
183  connect(m_schedInfoButton, SIGNAL(Clicked()), SLOT(ShowSchedInfo()));
184  if (m_previewButton)
185  connect(m_previewButton, SIGNAL(Clicked()), SLOT(ShowPreview()));
186  if (m_metadataButton)
187  connect(m_metadataButton, SIGNAL(Clicked()), SLOT(ShowMetadataOptions()));
188 
189  if (m_cancelButton)
190  connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
191  connect(m_saveButton, SIGNAL(Clicked()), SLOT(Save()));
192 
193  if (m_schedInfoButton)
195  if (m_previewButton)
197 
198  if (m_dupmethodList)
199  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
201  if (m_filtersList)
202  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
204  if (m_maxepSpin)
205  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
207  if (m_recgroupList)
208  connect(m_recgroupList, SIGNAL(LosingFocus()),
209  SLOT(PromptForRecGroup()));
210  if (m_transcodeCheck)
211  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
212  SLOT(TranscodeChanged(bool)));
213 
214  BuildFocusList();
215 
216  if (!m_recordingRule->IsLoaded())
217  {
218  if (m_recInfo)
220  else if (m_recordingRule->m_recordID)
222 
223  if (!m_recordingRule->IsLoaded())
224  {
225  LOG(VB_GENERAL, LOG_ERR,
226  "ScheduleEditor::Create() - Failed to load recording rule");
227  return false;
228  }
229  }
230 
231  if (m_player)
232  m_player->StartEmbedding(QRect());
233 
234  return true;
235 }
236 
238 {
239  if (m_child)
240  m_child->Close();
241 
242  // don't fade the screen if we are returning to the player
243  if (m_player)
244  GetScreenStack()->PopScreen(this, false);
245  else
246  GetScreenStack()->PopScreen(this, true);
247 }
248 
250 {
255 
256  if (!m_loaded)
257  {
258  // Copy this now, it will change briefly after the first item
259  // is inserted into the list by design of
260  // MythUIButtonList::itemSelected()
262 
263  // Rules List
265  {
267  .compare("Default", Qt::CaseInsensitive) != 0)
268  {
270  tr("Delete this recording rule template"),
272  }
276  }
277  else if (m_recordingRule->m_isOverride)
278  {
280  tr("Record this showing with normal options"),
288  }
289  else
290  {
291  bool hasChannel = !m_recordingRule->m_station.isEmpty();
292  bool isManual = (m_recordingRule->m_searchType == kManualSearch);
293 
297  if (hasChannel)
301  if (!isManual)
305  if (!hasChannel || isManual)
309  if (!hasChannel || isManual)
313  if (!isManual)
317  }
318 
320  }
322 
323  InfoMap progMap;
324 
325  m_recordingRule->ToMap(progMap);
326 
327  if (m_recInfo)
328  m_recInfo->ToMap(progMap);
329 
330  SetTextFromMap(progMap);
331 
332  m_loaded = true;
333 }
334 
336 {
338  Load();
339  emit templateLoaded();
340 }
341 
343 {
344  if (!item)
345  return;
346 
347  m_recordingRule->m_type = static_cast<RecordingType>
348  (item->GetData().toInt());
349 
350  bool isScheduled = (m_recordingRule->m_type != kNotRecording &&
352 
353  if (m_schedOptButton)
354  m_schedOptButton->SetEnabled(isScheduled);
355  if (m_filtersButton)
356  m_filtersButton->SetEnabled(isScheduled);
357  if (m_storeOptButton)
358  m_storeOptButton->SetEnabled(isScheduled);
359  if (m_postProcButton)
360  m_postProcButton->SetEnabled(isScheduled);
361  if (m_metadataButton)
362  m_metadataButton->SetEnabled(isScheduled &&
364 
369 }
370 
372 {
374 }
375 
377 {
379 }
380 
382 {
384 }
385 
387 {
389 }
390 
392 {
394 }
395 
397 {
398  if (m_child)
399  m_child->Close();
400 
402  {
403  int recid = m_recordingRule->m_recordID;
404  DeleteRule();
405  if (recid)
406  emit ruleDeleted(recid);
407  Close();
408  return;
409  }
410 
415  m_recordingRule->Save(true);
417 
418  Close();
419 }
420 
422 {
424 }
425 
427 {
430  return;
431 
432  if (m_child)
433  m_child->Close();
434 
436 
438  SchedOptEditor *schedoptedit = new SchedOptEditor(mainStack, *this,
440  if (!schedoptedit->Create())
441  {
442  delete schedoptedit;
443  return;
444  }
445 
447  m_child = schedoptedit;
448  mainStack->AddScreen(schedoptedit);
449 }
450 
452 {
455  return;
456 
457  if (m_child)
458  m_child->Close();
459 
461 
463  StoreOptEditor *storeoptedit = new StoreOptEditor(mainStack, *this,
465  if (!storeoptedit->Create())
466  {
467  delete storeoptedit;
468  return;
469  }
470 
472  m_child = storeoptedit;
473  mainStack->AddScreen(storeoptedit);
474 }
475 
477 {
480  return;
481 
482  if (m_child)
483  m_child->Close();
484 
486 
488  PostProcEditor *ppedit = new PostProcEditor(mainStack, *this,
490  if (!ppedit->Create())
491  {
492  delete ppedit;
493  return;
494  }
495 
497  m_child = ppedit;
498  mainStack->AddScreen(ppedit);
499 }
500 
502 {
504  return;
505 
506  QString label = tr("Schedule Information");
507 
508  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
509  MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
510 
511  if (menuPopup->Create())
512  {
513  menuPopup->SetReturnEvent(this, "schedinfo");
514 
515  if (m_recInfo)
516  menuPopup->AddButton(tr("Program Details"));
517  menuPopup->AddButton(tr("Upcoming Episodes"));
518  menuPopup->AddButton(tr("Upcoming Recordings"));
520  menuPopup->AddButton(tr("Previously Recorded"));
521 
522  popupStack->AddScreen(menuPopup);
523  }
524  else
525  delete menuPopup;
526 }
527 
528 bool ScheduleEditor::keyPressEvent(QKeyEvent *event)
529 {
530  if (GetFocusWidget()->keyPressEvent(event))
531  return true;
532 
533  QStringList actions;
534  bool handled = GetMythMainWindow()->
535  TranslateKeyPress("TV Frontend", event, actions);
536 
537  for (int i = 0; i < actions.size() && !handled; i++)
538  {
539  QString action = actions[i];
540  handled = true;
541 
542  if (action == "MENU")
543  showMenu();
544  else if (action == "INFO")
545  ShowDetails();
546  else if (action == "GUIDE")
547  ShowGuide();
548  else if (action == "UPCOMING")
550  else if (action == "PREVVIEW")
552  else if (action == "NEXTVIEW")
553  ShowNextView();
554  else
555  handled = false;
556  }
557 
558  if (!handled && MythScreenType::keyPressEvent(event))
559  handled = true;
560 
561  return handled;
562 }
563 
564 void ScheduleEditor::customEvent(QEvent *event)
565 {
566  if (event->type() == DialogCompletionEvent::kEventType)
567  {
569 
570  QString resultid = dce->GetId();
571  QString resulttext = dce->GetResultText();
572 
573  if (resultid == "menu")
574  {
575  if (resulttext == tr("Main Options"))
576  m_child->Close();
577  if (resulttext == tr("Schedule Options"))
578  ShowSchedOpt();
579  else if (resulttext == tr("Filter Options"))
580  ShowFilters();
581  else if (resulttext == tr("Storage Options"))
582  ShowStoreOpt();
583  else if (resulttext == tr("Post Processing"))
584  ShowPostProc();
585  else if (resulttext == tr("Metadata Options"))
587  else if (resulttext == tr("Use Template"))
589  else if (resulttext == tr("Schedule Info"))
590  ShowSchedInfo();
591  else if (resulttext == tr("Preview Changes"))
592  ShowPreview();
593  }
594  else if (resultid == "templatemenu")
595  {
596  LoadTemplate(resulttext);
597  }
598  else if (resultid == "schedinfo")
599  {
600  if (resulttext == tr("Program Details"))
601  ShowDetails();
602  else if (resulttext == tr("Upcoming Episodes"))
604  else if (resulttext == tr("Upcoming Recordings"))
606  else if (resulttext == tr("Previously Recorded"))
609  }
610  else if (resultid == "newrecgroup")
611  {
612  int groupID = CreateRecordingGroup(resulttext);
613  StoreOptMixin::SetRecGroup(groupID, resulttext);
614  }
615  }
616 }
617 
619 {
621  return;
622 
623  // No rule? Search by title
624  if (m_recordingRule->m_recordID <= 0)
625  {
627  return;
628  }
629 
631  ProgLister *pl = new ProgLister(mainStack, plRecordid,
632  QString::number(m_recordingRule->m_recordID),
633  "");
634 
635  if (pl->Create())
636  mainStack->AddScreen(pl);
637  else
638  delete pl;
639 }
640 
642 {
644  return;
645 
646  // Existing rule and search? Search by rule
647  if (m_recordingRule->m_recordID > 0 &&
650 
651  QString title = m_recordingRule->m_title;
652 
654  title.remove(QRegExp(" \\(.*\\)$"));
655 
657 }
658 
660 {
662  return;
663 
664  if (m_child)
665  {
666  m_child->Save();
667  if (m_view == kSchedOptView)
669  else if (m_view == kStoreOptView)
671  else if (m_view == kPostProcView)
673  }
674 
679 
680  QString ttable = "record_tmp";
681  m_recordingRule->UseTempTable(true, ttable);
682 
684  ViewScheduleDiff *vsd = new ViewScheduleDiff(mainStack, ttable,
687  if (vsd->Create())
688  mainStack->AddScreen(vsd);
689  else
690  delete vsd;
691 
693 }
694 
696 {
700  return;
701 
702  if (m_child)
703  m_child->Close();
704 
706  MetadataOptions *rad = new MetadataOptions(mainStack, *this,
708  if (!rad->Create())
709  {
710  delete rad;
711  return;
712  }
713 
715  m_child = rad;
716  mainStack->AddScreen(rad);
717 }
718 
720 {
723  return;
724 
725  if (m_child)
726  m_child->Close();
727 
729 
731  SchedFilterEditor *schedfilteredit = new SchedFilterEditor(mainStack,
732  *this, *m_recordingRule, m_recInfo);
733  if (!schedfilteredit->Create())
734  {
735  delete schedfilteredit;
736  return;
737  }
738 
740  m_child = schedfilteredit;
741  mainStack->AddScreen(schedfilteredit);
742 }
743 
745 {
748  return;
749 
752  else if (m_view == kMainView)
753  ShowPostProc();
754  else if (m_view == kSchedOptView)
755  m_child->Close();
756  else if (m_view == kFilterView)
757  ShowSchedOpt();
758  else if (m_view == kStoreOptView)
759  ShowFilters();
760  else if (m_view == kPostProcView)
761  ShowStoreOpt();
762  else if (m_view == kMetadataView)
763  ShowPostProc();
764 }
765 
767 {
770  return;
771 
772  if (m_view == kMainView)
773  ShowSchedOpt();
774  else if (m_view == kSchedOptView)
775  ShowFilters();
776  else if (m_view == kFilterView)
777  ShowStoreOpt();
778  else if (m_view == kStoreOptView)
779  ShowPostProc();
782  else if (m_view == kPostProcView)
783  m_child->Close();
784  else if (m_view == kMetadataView)
785  m_child->Close();
786 }
787 
789 {
790  if (m_view == kSchedOptView)
792  else if (m_view == kFilterView)
794  else if (m_view == kStoreOptView)
796  else if (m_view == kPostProcView)
798 
799  m_child = nullptr;
800  m_view = kMainView;
801 }
802 
804 {
805  QString label = tr("Options");
806  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
807  MythDialogBox *menuPopup =
808  new MythDialogBox(label, popupStack, "menuPopup");
809 
811  RecordingType type = static_cast<RecordingType>(item->GetData().toInt());
812  bool isScheduled = (type != kNotRecording && type != kDontRecord);
813 
814  if (menuPopup->Create())
815  {
816  menuPopup->SetReturnEvent(this, "menu");
817  if (m_view != kMainView)
818  menuPopup->AddButton(tr("Main Options"));
819  if (isScheduled && m_view != kSchedOptView)
820  menuPopup->AddButton(tr("Schedule Options"));
821  if (isScheduled && m_view != kFilterView)
822  menuPopup->AddButton(tr("Filter Options"));
823  if (isScheduled && m_view != kStoreOptView)
824  menuPopup->AddButton(tr("Storage Options"));
825  if (isScheduled && m_view != kPostProcView)
826  menuPopup->AddButton(tr("Post Processing"));
827  if (isScheduled && !m_recordingRule->m_isTemplate &&
829  menuPopup->AddButton(tr("Metadata Options"));
831  menuPopup->AddButton(tr("Schedule Info"));
833  menuPopup->AddButton(tr("Preview Changes"));
834  menuPopup->AddButton(tr("Use Template"));
835  popupStack->AddScreen(menuPopup);
836  }
837  else
838  {
839  delete menuPopup;
840  }
841 }
842 
844 {
845  QStringList templates = RecordingRule::GetTemplateNames();
846  if (templates.empty())
847  {
848  ShowOkPopup(tr("No templates available"));
849  return;
850  }
851 
852  QString label = tr("Template Options");
853  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
854  MythDialogBox *menuPopup =
855  new MythDialogBox(label, popupStack, "menuPopup");
856 
857  if (menuPopup->Create())
858  {
859  menuPopup->SetReturnEvent(this, "templatemenu");
860  while (!templates.empty())
861  {
862  QString name = templates.front();
863  if (name == "Default")
864  menuPopup->AddButton(tr("Default"));
865  else
866  menuPopup->AddButton(name);
867  templates.pop_front();
868  }
869  popupStack->AddScreen(menuPopup);
870  }
871  else
872  {
873  delete menuPopup;
874  }
875 }
876 
878 
884  ScheduleEditor &editor, RecordingRule &rule,
885  RecordingInfo *recInfo)
886  : MythScreenType(parent, name),
887  m_editor(&editor), m_recordingRule(&rule), m_recInfo(recInfo),
888  m_backButton(nullptr), m_saveButton(nullptr), m_previewButton(nullptr)
889 {
890 }
891 
892 bool SchedEditChild::keyPressEvent(QKeyEvent *event)
893 {
894  if (GetFocusWidget()->keyPressEvent(event))
895  return true;
896 
897  QStringList actions;
898  bool handled = GetMythMainWindow()->
899  TranslateKeyPress("TV Frontend", event, actions);
900 
901  for (int i = 0; i < actions.size() && !handled; i++)
902  {
903  QString action = actions[i];
904  handled = true;
905 
906  if (action == "MENU")
907  m_editor->showMenu();
908  else if (action == "INFO")
910  else if (action == "UPCOMING")
912  if (action == "ESCAPE")
913  Close();
914  else if (action == "PREVVIEW")
916  else if (action == "NEXTVIEW")
918  else
919  handled = false;
920  }
921 
922  if (!handled && MythScreenType::keyPressEvent(event))
923  handled = true;
924 
925  return handled;
926 }
927 
929  const QString &xmlfile, const QString &winname, bool isTemplate)
930 {
931  if (!LoadWindowFromXML(xmlfile, winname, this))
932  return false;
933 
934  UIUtilW::Assign(this, m_backButton, "back");
935  UIUtilW::Assign(this, m_saveButton, "save");
936  UIUtilW::Assign(this, m_previewButton, "preview");
937 
938  connect(this, SIGNAL(Closing()), m_editor, SLOT(ChildClosing()));
939  connect(m_editor, SIGNAL(templateLoaded()), SLOT(Load()));
940 
941  if (m_backButton)
942  connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
943  if (m_saveButton)
944  connect(m_saveButton, SIGNAL(Clicked()), m_editor, SLOT(Save()));
945  if (m_previewButton)
946  connect(m_previewButton, SIGNAL(Clicked()),
947  m_editor, SLOT(ShowPreview()));
948 
949  if (m_previewButton)
950  m_previewButton->SetEnabled(!isTemplate);
951 
952  return true;
953 }
954 
956 {
957  InfoMap progMap;
958 
959  m_recordingRule->ToMap(progMap);
960 
961  if (m_recInfo)
962  m_recInfo->ToMap(progMap);
963 
964  SetTextFromMap(progMap);
965 }
966 
968 {
969  Save();
970  emit Closing();
972 }
973 
975 
982  ScheduleEditor &editor,
983  RecordingRule &rule,
984  RecordingInfo *recInfo)
985  : SchedEditChild(parent, "ScheduleOptionsEditor", editor, rule, recInfo),
986  SchedOptMixin(*this, &rule, &editor), m_filtersButton(nullptr)
987 {
988 }
989 
991 {
993  "schedule-ui.xml", "scheduleoptionseditor",
995  {
996  return false;
997  }
998 
999  bool err = false;
1000 
1001  SchedOptMixin::Create(&err);
1002 
1003  UIUtilW::Assign(this, m_filtersButton, "filters");
1004 
1005  if (err)
1006  {
1007  LOG(VB_GENERAL, LOG_ERR, "SchedOptEditor, theme is missing "
1008  "required elements");
1009  return false;
1010  }
1011 
1012  if (m_dupmethodList)
1013  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
1015 
1016  if (m_filtersButton)
1017  connect(m_filtersButton, SIGNAL(Clicked()),
1018  m_editor, SLOT(ShowFilters()));
1019 
1020  BuildFocusList();
1021 
1022  return true;
1023 }
1024 
1026 {
1028  SetTextFromMaps();
1029 }
1030 
1032 {
1034 }
1035 
1037 {
1039 }
1040 
1042 
1049  ScheduleEditor &editor,
1050  RecordingRule &rule,
1051  RecordingInfo *recInfo)
1052  : SchedEditChild(parent, "ScheduleFilterEditor", editor, rule, recInfo),
1053  FilterOptMixin(*this, &rule, &editor)
1054 {
1055 }
1056 
1058 {
1060  "schedule-ui.xml", "schedulefiltereditor",
1062  {
1063  return false;
1064  }
1065 
1066  bool err = false;
1067 
1068  FilterOptMixin::Create(&err);
1069 
1070  if (err)
1071  {
1072  LOG(VB_GENERAL, LOG_ERR, "SchedFilterEditor, theme is missing "
1073  "required elements");
1074  return false;
1075  }
1076 
1077  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
1079 
1080  BuildFocusList();
1081 
1082  return true;
1083 }
1084 
1086 {
1088  SetTextFromMaps();
1089 }
1090 
1092 {
1094 }
1095 
1097 {
1099 }
1100 
1102 
1109  ScheduleEditor &editor,
1110  RecordingRule &rule,
1111  RecordingInfo *recInfo)
1112  : SchedEditChild(parent, "StorageOptionsEditor", editor, rule, recInfo),
1113  StoreOptMixin(*this, &rule, &editor)
1114 {
1115 }
1116 
1118 {
1120  "schedule-ui.xml", "storageoptionseditor",
1122  {
1123  return false;
1124  }
1125 
1126  bool err = false;
1127 
1128  StoreOptMixin::Create(&err);
1129 
1130  if (err)
1131  {
1132  LOG(VB_GENERAL, LOG_ERR, "StoreOptEditor, theme is missing "
1133  "required elements");
1134  return false;
1135  }
1136 
1137  if (m_maxepSpin)
1138  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
1140  if (m_recgroupList)
1141  connect(m_recgroupList, SIGNAL(LosingFocus()),
1142  SLOT(PromptForRecGroup()));
1143 
1144  BuildFocusList();
1145 
1146  return true;
1147 }
1148 
1150 {
1152  SetTextFromMaps();
1153 }
1154 
1156 {
1158 }
1159 
1161 {
1163 }
1164 
1165 void StoreOptEditor::customEvent(QEvent *event)
1166 {
1167  if (event->type() == DialogCompletionEvent::kEventType)
1168  {
1170 
1171  QString resultid = dce->GetId();
1172  QString resulttext = dce->GetResultText();
1173 
1174  if (resultid == "newrecgroup")
1175  {
1176  int groupID = CreateRecordingGroup(resulttext);
1177  StoreOptMixin::SetRecGroup(groupID, resulttext);
1178  }
1179  }
1180 }
1181 
1183 {
1185 }
1186 
1188 
1195  ScheduleEditor &editor,
1196  RecordingRule &rule,
1197  RecordingInfo *recInfo)
1198  : SchedEditChild(parent, "PostProcOptionsEditor", editor, rule, recInfo),
1199  PostProcMixin(*this, &rule, &editor)
1200 {
1201 }
1202 
1204 {
1206  "schedule-ui.xml", "postproceditor",
1208  {
1209  return false;
1210  }
1211 
1212  bool err = false;
1213 
1214  PostProcMixin::Create(&err);
1215 
1216  if (err)
1217  {
1218  LOG(VB_GENERAL, LOG_ERR, "PostProcEditor, theme is missing "
1219  "required elements");
1220  return false;
1221  }
1222 
1223  if (m_transcodeCheck)
1224  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
1225  SLOT(TranscodeChanged(bool)));
1226 
1227  BuildFocusList();
1228 
1229  return true;
1230 }
1231 
1233 {
1235  SetTextFromMaps();
1236 }
1237 
1239 {
1241 }
1242 
1244 {
1246 }
1247 
1249 
1256  ScheduleEditor &editor,
1257  RecordingRule &rule,
1258  RecordingInfo *recInfo)
1259  : SchedEditChild(parent, "MetadataOptions", editor, rule, recInfo),
1260  m_busyPopup(nullptr), m_fanart(nullptr), m_coverart(nullptr),
1261  m_banner(nullptr), m_inetrefEdit(nullptr), m_seasonSpin(nullptr),
1262  m_episodeSpin(nullptr), m_queryButton(nullptr), m_localFanartButton(nullptr),
1263  m_localCoverartButton(nullptr), m_localBannerButton(nullptr),
1264  m_onlineFanartButton(nullptr), m_onlineCoverartButton(nullptr),
1265  m_onlineBannerButton(nullptr)
1266 {
1267  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
1268 
1269  m_metadataFactory = new MetadataFactory(this);
1270  m_imageLookup = new MetadataDownload(this);
1272 
1275 }
1276 
1278 {
1279  if (m_imageLookup)
1280  {
1281  m_imageLookup->cancel();
1282  delete m_imageLookup;
1283  m_imageLookup = nullptr;
1284  }
1285 
1286  if (m_imageDownload)
1287  {
1289  delete m_imageDownload;
1290  m_imageDownload = nullptr;
1291  }
1292 }
1293 
1295 {
1297  "schedule-ui.xml", "metadataoptions",
1299  {
1300  return false;
1301  }
1302 
1303  bool err = false;
1304 
1305  UIUtilE::Assign(this, m_inetrefEdit, "inetref_edit", &err);
1306  UIUtilE::Assign(this, m_seasonSpin, "season_spinbox", &err);
1307  UIUtilE::Assign(this, m_episodeSpin, "episode_spinbox", &err);
1308  UIUtilE::Assign(this, m_queryButton, "query_button", &err);
1309  UIUtilE::Assign(this, m_localFanartButton, "local_fanart_button", &err);
1310  UIUtilE::Assign(this, m_localCoverartButton, "local_coverart_button", &err);
1311  UIUtilE::Assign(this, m_localBannerButton, "local_banner_button", &err);
1312  UIUtilE::Assign(this, m_onlineFanartButton, "online_fanart_button", &err);
1313  UIUtilE::Assign(this, m_onlineCoverartButton, "online_coverart_button", &err);
1314  UIUtilE::Assign(this, m_onlineBannerButton, "online_banner_button", &err);
1315  UIUtilW::Assign(this, m_fanart, "fanart");
1316  UIUtilW::Assign(this, m_coverart, "coverart");
1317  UIUtilW::Assign(this, m_banner, "banner");
1318 
1319  if (err)
1320  {
1321  LOG(VB_GENERAL, LOG_ERR, "MetadataOptions, theme is missing "
1322  "required elements");
1323  return false;
1324  }
1325 
1326  connect(m_queryButton, SIGNAL(Clicked()),
1327  SLOT(PerformQuery()));
1328  connect(m_localFanartButton, SIGNAL(Clicked()),
1329  SLOT(SelectLocalFanart()));
1330  connect(m_localCoverartButton, SIGNAL(Clicked()),
1331  SLOT(SelectLocalCoverart()));
1332  connect(m_localBannerButton, SIGNAL(Clicked()),
1333  SLOT(SelectLocalBanner()));
1334  connect(m_onlineFanartButton, SIGNAL(Clicked()),
1335  SLOT(SelectOnlineFanart()));
1336  connect(m_onlineCoverartButton, SIGNAL(Clicked()),
1337  SLOT(SelectOnlineCoverart()));
1338  connect(m_onlineBannerButton, SIGNAL(Clicked()),
1339  SLOT(SelectOnlineBanner()));
1340 
1341  connect(m_seasonSpin, SIGNAL(itemSelected(MythUIButtonListItem*)),
1342  SLOT(ValuesChanged()));
1343 
1344  // InetRef
1346 
1347  // Season
1348  m_seasonSpin->SetRange(0,9999,1,5);
1350 
1351  // Episode
1352  m_episodeSpin->SetRange(0,9999,1,10);
1354 
1355  if (m_coverart)
1356  {
1358  m_coverart->Load();
1359  }
1360 
1361  if (m_fanart)
1362  {
1364  m_fanart->Load();
1365  }
1366 
1367  if (m_banner)
1368  {
1370  m_banner->Load();
1371  }
1372 
1373  BuildFocusList();
1374 
1375  return true;
1376 }
1377 
1379 {
1380  SetTextFromMaps();
1381 }
1382 
1384 {
1385  if (m_busyPopup)
1386  return;
1387 
1388  QString message = title;
1389 
1390  m_busyPopup = new MythUIBusyDialog(message, m_popupStack,
1391  "metaoptsdialog");
1392 
1393  if (m_busyPopup->Create())
1395 }
1396 
1398 {
1399  CreateBusyDialog(tr("Trying to manually find this "
1400  "recording online..."));
1401 
1403 
1404  lookup->SetAutomatic(false);
1405  m_metadataFactory->Lookup(lookup);
1406 }
1407 
1409 {
1410  QueryComplete(lookup);
1411 }
1412 
1415 {
1416  QString msg = tr("Downloading selected artwork...");
1417  CreateBusyDialog(msg);
1418 
1419  MetadataLookup *lookup = new MetadataLookup();
1420 
1421  lookup->SetType(kMetadataVideo);
1423  lookup->SetAutomatic(true);
1424  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1425 
1426  ArtworkMap downloads;
1427  downloads.insert(type, info);
1428  lookup->SetDownloads(downloads);
1429  lookup->SetAllowOverwrites(true);
1430  lookup->SetTitle(m_recordingRule->m_title);
1432  lookup->SetInetref(m_inetrefEdit->GetText());
1433  lookup->SetSeason(m_seasonSpin->GetIntValue());
1434  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1435 
1436  m_imageDownload->addDownloads(lookup);
1437 }
1438 
1440 {
1441  if (!CanSetArtwork())
1442  return;
1443 
1444  QString url = generate_file_url("Fanart",
1446  "");
1447  FindImagePopup(url,"",*this, "fanart");
1448 }
1449 
1451 {
1452  if (!CanSetArtwork())
1453  return;
1454 
1455  QString url = generate_file_url("Coverart",
1457  "");
1458  FindImagePopup(url,"",*this, "coverart");
1459 }
1460 
1462 {
1463  if (!CanSetArtwork())
1464  return;
1465 
1466  QString url = generate_file_url("Banners",
1468  "");
1469  FindImagePopup(url,"",*this, "banner");
1470 }
1471 
1473 {
1475 }
1476 
1478 {
1480 }
1481 
1483 {
1485 }
1486 
1488 {
1489  // Season
1490  if (m_seasonSpin)
1492 
1493  // Episode
1494  if (m_episodeSpin)
1496 
1497  // InetRef
1498  if (m_inetrefEdit)
1500 }
1501 
1503 {
1504  if (!lookup)
1505  return;
1506 
1507  // InetRef
1508  m_inetrefEdit->SetText(lookup->GetInetref());
1509 
1510  // Season
1511  m_seasonSpin->SetValue(lookup->GetSeason());
1512 
1513  // Episode
1514  m_episodeSpin->SetValue(lookup->GetEpisode());
1515 
1516  InfoMap metadataMap;
1517  lookup->toMap(metadataMap);
1518  SetTextFromMap(metadataMap);
1519 }
1520 
1522  const QString &prefixAlt,
1523  QObject &inst,
1524  const QString &returnEvent)
1525 {
1526  QString fp;
1527 
1528  if (prefix.startsWith("myth://"))
1529  fp = prefix;
1530  else
1531  fp = prefix.isEmpty() ? prefixAlt : prefix;
1532 
1533  MythScreenStack *popupStack =
1534  GetMythMainWindow()->GetStack("popup stack");
1535 
1536  MythUIFileBrowser *fb = new MythUIFileBrowser(popupStack, fp);
1538  if (fb->Create())
1539  {
1540  fb->SetReturnEvent(&inst, returnEvent);
1541  popupStack->AddScreen(fb);
1542  }
1543  else
1544  delete fb;
1545 }
1546 
1548 {
1549  QStringList ret;
1550 
1551  QList<QByteArray> exts = QImageReader::supportedImageFormats();
1552  for (QList<QByteArray>::iterator p = exts.begin(); p != exts.end(); ++p)
1553  {
1554  ret.append(QString("*.").append(*p));
1555  }
1556 
1557  return ret;
1558 }
1559 
1561 {
1562  if (m_inetrefEdit->GetText().isEmpty())
1563  {
1564  ShowOkPopup(tr("You must set a reference number "
1565  "on this rule to set artwork. For items "
1566  "without a metadata source, you can set "
1567  "any unique value."));
1568  return false;
1569  }
1570 
1571  return true;
1572 }
1573 
1575 {
1576  MetadataLookup *lookup = new MetadataLookup();
1577  lookup->SetStep(kLookupSearch);
1578  lookup->SetType(mtype);
1580 
1581  if (type == kUnknownVideo)
1582  {
1584  (m_seasonSpin->GetIntValue() == 0 &&
1585  m_episodeSpin->GetIntValue() == 0))
1586  {
1587  lookup->SetSubtype(kProbableMovie);
1588  }
1589  else
1590  {
1592  }
1593  }
1594  else
1595  {
1596  // we could determine the type from the inetref
1597  lookup->SetSubtype(type);
1598  }
1599  lookup->SetAllowGeneric(true);
1600  lookup->SetHandleImages(false);
1602  lookup->SetTitle(m_recordingRule->m_title);
1604  lookup->SetInetref(m_inetrefEdit->GetText());
1606  lookup->SetSeason(m_seasonSpin->GetIntValue());
1607  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1608 
1609  return lookup;
1610 }
1611 
1613 {
1614  if (!CanSetArtwork())
1615  return;
1616 
1617  QString msg = tr("Searching for available artwork...");
1618  CreateBusyDialog(msg);
1619 
1621 
1622  lookup->SetAutomatic(true);
1623  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1624  m_imageLookup->addLookup(lookup);
1625 }
1626 
1628 {
1629  if (!lookup)
1630  return;
1631 
1632  if (m_busyPopup)
1633  {
1634  m_busyPopup->Close();
1635  m_busyPopup = nullptr;
1636  }
1637 
1638  VideoArtworkType type = lookup->GetData().value<VideoArtworkType>();
1639  ArtworkList list = lookup->GetArtwork(type);
1640 
1641  if (list.isEmpty())
1642  {
1643  MythWarningNotification n(tr("No image found"), tr("Schedule Editor"));
1645  return;
1646  }
1647 
1648  ImageSearchResultsDialog *resultsdialog =
1650 
1651  connect(resultsdialog, SIGNAL(haveResult(ArtworkInfo, VideoArtworkType)),
1653 
1654  if (resultsdialog->Create())
1655  m_popupStack->AddScreen(resultsdialog);
1656 }
1657 
1659 {
1660  if (!lookup)
1661  return;
1662 
1663  DownloadMap map = lookup->GetDownloads();
1664 
1665  if (map.isEmpty())
1666  return;
1667 
1668  for (DownloadMap::const_iterator i = map.begin(); i != map.end(); ++i)
1669  {
1670  VideoArtworkType type = i.key();
1671  ArtworkInfo info = i.value();
1672 
1673  if (type == kArtworkCoverart)
1674  m_artworkMap.replace(kArtworkCoverart, info);
1675  else if (type == kArtworkFanart)
1676  m_artworkMap.replace(kArtworkFanart, info);
1677  else if (type == kArtworkBanner)
1678  m_artworkMap.replace(kArtworkBanner, info);
1679  }
1680 
1683 
1684  ValuesChanged();
1685 }
1686 
1688 {
1691 
1692  if (m_coverart)
1693  {
1695  m_coverart->Load();
1696  }
1697 
1698  if (m_fanart)
1699  {
1701  m_fanart->Load();
1702  }
1703 
1704  if (m_banner)
1705  {
1707  m_banner->Load();
1708  }
1709 }
1710 
1711 void MetadataOptions::customEvent(QEvent *levent)
1712 {
1713  if (levent->type() == MetadataFactoryMultiResult::kEventType)
1714  {
1715  if (m_busyPopup)
1716  {
1717  m_busyPopup->Close();
1718  m_busyPopup = nullptr;
1719  }
1720 
1721  MetadataFactoryMultiResult *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
1722 
1723  if (!mfmr)
1724  return;
1725 
1726  MetadataLookupList list = mfmr->results;
1727 
1728  if (list.count() > 1)
1729  {
1730  int yearindex = -1;
1731 
1732  for (int p = 0; p != list.size(); ++p)
1733  {
1734  if (!m_recordingRule->m_seriesid.isEmpty() &&
1735  m_recordingRule->m_seriesid == (list[p])->GetTMSref())
1736  {
1737  MetadataLookup *lookup = list[p];
1738  QueryComplete(lookup);
1739  return;
1740  }
1741  else if (m_recInfo &&
1743  (list[p])->GetYear() != 0 &&
1744  m_recInfo->GetYearOfInitialRelease() == (list[p])->GetYear())
1745  {
1746  if (yearindex > -1)
1747  {
1748  LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
1749  "match could be found based on year alone.");
1750  yearindex = -2;
1751  }
1752  else if (yearindex == -1)
1753  {
1754  LOG(VB_GENERAL, LOG_INFO, "Matched based on year. ");
1755  yearindex = p;
1756  }
1757  }
1758  }
1759 
1760  if (yearindex > -1)
1761  {
1762  MetadataLookup *lookup = list[yearindex];
1763  QueryComplete(lookup);
1764  return;
1765  }
1766 
1767  LOG(VB_GENERAL, LOG_INFO, "Falling through to selection dialog.");
1768  MetadataResultsDialog *resultsdialog =
1770 
1771  connect(resultsdialog, SIGNAL(haveResult(RefCountHandler<MetadataLookup>)),
1773  Qt::QueuedConnection);
1774 
1775  if (resultsdialog->Create())
1776  m_popupStack->AddScreen(resultsdialog);
1777  }
1778  }
1779  else if (levent->type() == MetadataFactorySingleResult::kEventType)
1780  {
1781  if (m_busyPopup)
1782  {
1783  m_busyPopup->Close();
1784  m_busyPopup = nullptr;
1785  }
1786 
1787  MetadataFactorySingleResult *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
1788 
1789  if (!mfsr)
1790  return;
1791 
1792  MetadataLookup *lookup = mfsr->result;
1793 
1794  if (!lookup)
1795  return;
1796 
1797  QueryComplete(lookup);
1798  }
1799  else if (levent->type() == MetadataFactoryNoResult::kEventType)
1800  {
1801  if (m_busyPopup)
1802  {
1803  m_busyPopup->Close();
1804  m_busyPopup = nullptr;
1805  }
1806 
1807  MetadataFactoryNoResult *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
1808 
1809  if (!mfnr)
1810  return;
1811 
1812  QString title = tr("No match found for this recording. You can "
1813  "try entering a TVDB/TMDB number, season, and "
1814  "episode manually.");
1815 
1816  MythConfirmationDialog *okPopup =
1817  new MythConfirmationDialog(m_popupStack, title, false);
1818 
1819  if (okPopup->Create())
1820  m_popupStack->AddScreen(okPopup);
1821  }
1822  else if (levent->type() == MetadataLookupEvent::kEventType)
1823  {
1824  if (m_busyPopup)
1825  {
1826  m_busyPopup->Close();
1827  m_busyPopup = nullptr;
1828  }
1829 
1830  MetadataLookupEvent *lue = (MetadataLookupEvent *)levent;
1831 
1832  MetadataLookupList lul = lue->lookupList;
1833 
1834  if (lul.isEmpty())
1835  return;
1836 
1837  if (lul.count() >= 1)
1838  {
1839  OnArtworkSearchDone(lul[0]);
1840  }
1841  }
1842  else if (levent->type() == MetadataLookupFailure::kEventType)
1843  {
1844  if (m_busyPopup)
1845  {
1846  m_busyPopup->Close();
1847  m_busyPopup = nullptr;
1848  }
1849 
1851 
1852  MetadataLookupList lul = luf->lookupList;
1853 
1854  if (lul.size())
1855  {
1856  QString title = tr("This number, season, and episode combination "
1857  "does not appear to be valid (or the site may "
1858  "be down). Check your information and try "
1859  "again.");
1860 
1861  MythConfirmationDialog *okPopup =
1862  new MythConfirmationDialog(m_popupStack, title, false);
1863 
1864  if (okPopup->Create())
1865  m_popupStack->AddScreen(okPopup);
1866  }
1867  }
1868  else if (levent->type() == ImageDLEvent::kEventType)
1869  {
1870  if (m_busyPopup)
1871  {
1872  m_busyPopup->Close();
1873  m_busyPopup = nullptr;
1874  }
1875 
1876  ImageDLEvent *ide = (ImageDLEvent *)levent;
1877 
1878  MetadataLookup *lookup = ide->item;
1879 
1880  if (!lookup)
1881  return;
1882 
1883  HandleDownloadedImages(lookup);
1884  }
1885  else if (levent->type() == ImageDLFailureEvent::kEventType)
1886  {
1887  if (m_busyPopup)
1888  {
1889  m_busyPopup->Close();
1890  m_busyPopup = nullptr;
1891  }
1892  MythErrorNotification n(tr("Failed to retrieve image(s)"),
1893  tr("Schedule Editor"),
1894  tr("Check logs"));
1896  }
1897  else if (levent->type() == DialogCompletionEvent::kEventType)
1898  {
1899  DialogCompletionEvent *dce = (DialogCompletionEvent*)(levent);
1900 
1901  const QString resultid = dce->GetId();
1902  ArtworkInfo info;
1903  info.url = dce->GetResultText();
1904 
1905  if (resultid == "coverart")
1906  {
1907  m_artworkMap.replace(kArtworkCoverart, info);
1908  }
1909  else if (resultid == "fanart")
1910  {
1911  m_artworkMap.replace(kArtworkFanart, info);
1912  }
1913  else if (resultid == "banner")
1914  {
1915  m_artworkMap.replace(kArtworkBanner, info);
1916  }
1917 
1920 
1921  ValuesChanged();
1922  }
1923 
1924 }
1925 
1927 
1934  SchedOptMixin *other)
1935  : m_prioritySpin(nullptr), m_startoffsetSpin(nullptr), m_endoffsetSpin(nullptr),
1936  m_dupmethodList(nullptr), m_dupscopeList(nullptr), m_inputList(nullptr),
1937  m_ruleactiveCheck(nullptr), m_newrepeatList(nullptr),
1938  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false),
1939  m_haveRepeats(gCoreContext->GetBoolSetting("HaveRepeats", false))
1940 {
1941 }
1942 
1943 void SchedOptMixin::Create(bool *err)
1944 {
1945  if (!m_rule)
1946  return;
1947 
1948  if (m_other && !m_other->m_prioritySpin)
1949  UIUtilE::Assign(m_screen, m_prioritySpin, "priority", err);
1950  else
1951  UIUtilW::Assign(m_screen, m_prioritySpin, "priority");
1952 
1954  UIUtilE::Assign(m_screen, m_startoffsetSpin, "startoffset", err);
1955  else
1956  UIUtilW::Assign(m_screen, m_startoffsetSpin, "startoffset");
1957 
1958  if (m_other && !m_other->m_endoffsetSpin)
1959  UIUtilE::Assign(m_screen, m_endoffsetSpin, "endoffset", err);
1960  else
1961  UIUtilW::Assign(m_screen, m_endoffsetSpin, "endoffset");
1962 
1963  if (m_other && !m_other->m_dupmethodList)
1964  UIUtilE::Assign(m_screen, m_dupmethodList, "dupmethod", err);
1965  else
1966  UIUtilW::Assign(m_screen, m_dupmethodList, "dupmethod");
1967 
1968  if (m_other && !m_other->m_dupscopeList)
1969  UIUtilE::Assign(m_screen, m_dupscopeList, "dupscope", err);
1970  else
1971  UIUtilW::Assign(m_screen, m_dupscopeList, "dupscope");
1972 
1973  if (m_other && !m_other->m_inputList)
1974  UIUtilE::Assign(m_screen, m_inputList, "input", err);
1975  else
1977 
1979  UIUtilE::Assign(m_screen, m_ruleactiveCheck, "ruleactive", err);
1980  else
1981  UIUtilW::Assign(m_screen, m_ruleactiveCheck, "ruleactive");
1982 
1983  UIUtilW::Assign(m_screen, m_newrepeatList, "newrepeat");
1984 }
1985 
1987 {
1988  if (!m_rule)
1989  return;
1990 
1991  // Priority
1992  if (m_prioritySpin)
1993  {
1994  if (!m_loaded)
1995  m_prioritySpin->SetRange(-99,99,1,5);
1997  }
1998 
1999  // Start Offset
2000  if (m_startoffsetSpin)
2001  {
2002  if (!m_loaded)
2003  m_startoffsetSpin->SetRange(480,-480,1,10);
2005  }
2006 
2007  // End Offset
2008  if (m_endoffsetSpin)
2009  {
2010  if (!m_loaded)
2011  m_endoffsetSpin->SetRange(-480,480,1,10);
2013  }
2014 
2015  // Duplicate Match Type
2016  if (m_dupmethodList)
2017  {
2018  if (!m_loaded)
2019  {
2021 
2037 
2038  m_rule->m_dupMethod = dupMethod;
2039  }
2041  }
2042 
2043  // Duplicate Matching Scope
2044  if (m_dupscopeList)
2045  {
2046  if (!m_loaded)
2047  {
2057  if (m_haveRepeats && !m_newrepeatList &&
2059  {
2063  }
2064  }
2066  }
2067 
2068  // Preferred Input
2069  if (m_inputList)
2070  {
2071  if (!m_loaded)
2072  {
2074  QObject::tr("Use any available input"),
2075  qVariantFromValue(0));
2076 
2077  vector<uint> inputids = CardUtil::GetSchedInputList();
2078  for (uint i = 0; i < inputids.size(); ++i)
2079  {
2081  QObject::tr("Prefer input %1")
2082  .arg(CardUtil::GetDisplayName(inputids[i])), inputids[i]);
2083  }
2084  }
2086  }
2087 
2088  // Active/Disabled
2089  if (m_ruleactiveCheck)
2090  {
2092  }
2093 
2094  // Record new and repeat
2095  if (m_newrepeatList)
2096  {
2097  if (!m_loaded)
2098  {
2100  QObject::tr("Record new and repeat "
2101  "episodes"), ENUM_TO_QVARIANT(0));
2103  QObject::tr("Record new episodes only"),
2105  }
2107  (m_rule->m_dupIn & kDupsNewEpi));
2108  }
2109 
2110  m_loaded = true;
2111 
2112  RuleChanged();
2113 }
2114 
2116 {
2117  if (!m_rule)
2118  return;
2119 
2120  if (m_prioritySpin)
2122  if (m_startoffsetSpin)
2124  if (m_endoffsetSpin)
2126  if (m_dupmethodList)
2127  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2128  (m_dupmethodList->GetDataValue().toInt());
2129  if (m_dupscopeList)
2130  {
2131  int mask = ((m_other && m_other->m_newrepeatList) ||
2132  m_newrepeatList) ? kDupsInAll : ~0;
2133  int val = ((m_rule->m_dupIn & ~mask) |
2134  m_dupscopeList->GetDataValue().toInt());
2135  m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2136  }
2137  if (m_inputList)
2139  if (m_ruleactiveCheck)
2141  if (m_newrepeatList)
2142  {
2143  int val = ((m_rule->m_dupIn & ~kDupsNewEpi) |
2144  m_newrepeatList->GetDataValue().toInt());
2145  m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2146  }
2147 }
2148 
2150 {
2151  if (!m_rule)
2152  return;
2153 
2154  bool isScheduled = (m_rule->m_type != kNotRecording &&
2155  m_rule->m_type != kDontRecord);
2156  bool isSingle = (m_rule->m_type == kSingleRecord ||
2158 
2159  if (m_prioritySpin)
2160  m_prioritySpin->SetEnabled(isScheduled);
2161  if (m_startoffsetSpin)
2162  m_startoffsetSpin->SetEnabled(isScheduled);
2163  if (m_endoffsetSpin)
2164  m_endoffsetSpin->SetEnabled(isScheduled);
2165  if (m_dupmethodList)
2166  m_dupmethodList->SetEnabled(isScheduled && !isSingle);
2167  if (m_dupscopeList)
2168  m_dupscopeList->SetEnabled(isScheduled && !isSingle &&
2170  if (m_inputList)
2171  m_inputList->SetEnabled(isScheduled);
2172  if (m_ruleactiveCheck)
2173  m_ruleactiveCheck->SetEnabled(isScheduled);
2174  if (m_newrepeatList)
2175  m_newrepeatList->SetEnabled(isScheduled && !isSingle && m_haveRepeats);
2176 }
2177 
2179 {
2180  if (!item || !m_rule)
2181  return;
2182 
2183  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2184  (item->GetData().toInt());
2185 
2186  if (m_dupscopeList)
2188 }
2189 
2191 
2198  FilterOptMixin *other)
2199  : m_filtersList(nullptr), m_activeFiltersList(nullptr),
2200  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2201 {
2202 }
2203 
2204 void FilterOptMixin::Create(bool *err)
2205 {
2206  if (!m_rule)
2207  return;
2208 
2209  if (m_other && !m_other->m_filtersList)
2210  UIUtilE::Assign(m_screen, m_filtersList, "filters", err);
2211  else
2212  UIUtilW::Assign(m_screen, m_filtersList, "filters");
2213 
2214  UIUtilW::Assign(m_screen, m_activeFiltersList, "activefilters");
2215  if (m_activeFiltersList)
2217 }
2218 
2220 {
2221  if (!m_rule)
2222  return;
2223 
2224  if (!m_loaded)
2225  {
2226  MSqlQuery query(MSqlQuery::InitCon());
2227 
2228  query.prepare("SELECT filterid, description, newruledefault "
2229  "FROM recordfilter ORDER BY filterid");
2230 
2231  if (query.exec())
2232  {
2233  while (query.next())
2234  {
2235  m_descriptions << QObject::tr(query.value(1).toString()
2236  .toUtf8().constData());
2237  }
2238  }
2239  m_loaded = true;
2240  }
2241 
2242  if (m_activeFiltersList)
2244 
2245  MythUIButtonListItem *button;
2246  QStringList::iterator Idesc;
2247  int idx;
2248  bool not_empty = m_filtersList && !m_filtersList->IsEmpty();
2249  for (Idesc = m_descriptions.begin(), idx = 0;
2250  Idesc != m_descriptions.end(); ++Idesc, ++idx)
2251  {
2252  bool active = m_rule->m_filter & (1 << idx);
2253  if (m_filtersList)
2254  {
2255  if (not_empty)
2256  button = m_filtersList->GetItemAt(idx);
2257  else
2258  button = new MythUIButtonListItem(m_filtersList, *Idesc, idx);
2259  button->setCheckable(true);
2262  }
2263  if (active && m_activeFiltersList)
2264  {
2265  /* Create a simple list of active filters the theme can
2266  use for informational purposes. */
2268  *Idesc, idx);
2269  button->setCheckable(false);
2270  }
2271  }
2272 
2274  {
2276  QObject::tr("None"), idx);
2277  button->setCheckable(false);
2278  }
2279 
2280  RuleChanged();
2281 }
2282 
2284 {
2285  if (!m_rule || !m_filtersList)
2286  return;
2287 
2288  // Iterate through button list, and build the mask
2289  uint32_t filter_mask = 0;
2290  int idx, end;
2291 
2292  end = m_filtersList->GetCount();
2293  for (idx = 0; idx < end; ++idx)
2294  {
2295  MythUIButtonListItem *button;
2296  if ((button = m_filtersList->GetItemAt(idx)) &&
2298  filter_mask |= (1 << button->GetData().value<uint32_t>());
2299  }
2300  m_rule->m_filter = filter_mask;
2301 }
2302 
2304 {
2305  if (!m_rule)
2306  return;
2307 
2308  bool enabled = m_rule->m_type != kNotRecording &&
2310  if (m_filtersList)
2311  m_filtersList->SetEnabled(enabled);
2312  if (m_activeFiltersList)
2313  m_activeFiltersList->SetEnabled(enabled);
2314 }
2315 
2317 {
2321 }
2322 
2323 
2325 
2332  StoreOptMixin *other)
2333  : m_recprofileList(nullptr), m_recgroupList(nullptr), m_storagegroupList(nullptr),
2334  m_playgroupList(nullptr), m_maxepSpin(nullptr), m_maxbehaviourList(nullptr),
2335  m_autoexpireCheck(nullptr),
2336  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2337 {
2338 }
2339 
2340 void StoreOptMixin::Create(bool *err)
2341 {
2342  if (!m_rule)
2343  return;
2344 
2345  if (m_other && !m_other->m_recprofileList)
2346  UIUtilE::Assign(m_screen, m_recprofileList, "recprofile", err);
2347  else
2348  UIUtilW::Assign(m_screen, m_recprofileList, "recprofile");
2349 
2350  if (m_other && !m_other->m_recgroupList)
2351  UIUtilE::Assign(m_screen, m_recgroupList, "recgroup", err);
2352  else
2353  UIUtilW::Assign(m_screen, m_recgroupList, "recgroup");
2354 
2356  UIUtilE::Assign(m_screen, m_storagegroupList, "storagegroup", err);
2357  else
2358  UIUtilW::Assign(m_screen, m_storagegroupList, "storagegroup");
2359 
2360  if (m_other && !m_other->m_playgroupList)
2361  UIUtilE::Assign(m_screen, m_playgroupList, "playgroup", err);
2362  else
2363  UIUtilW::Assign(m_screen, m_playgroupList, "playgroup");
2364 
2365  if (m_other && !m_other->m_maxepSpin)
2366  UIUtilE::Assign(m_screen, m_maxepSpin, "maxepisodes", err);
2367  else
2368  UIUtilW::Assign(m_screen, m_maxepSpin, "maxepisodes");
2369 
2371  UIUtilE::Assign(m_screen, m_maxbehaviourList, "maxnewest", err);
2372  else
2374 
2376  UIUtilE::Assign(m_screen, m_autoexpireCheck, "autoexpire", err);
2377  else
2378  UIUtilW::Assign(m_screen, m_autoexpireCheck, "autoexpire");
2379 }
2380 
2382 {
2383  if (!m_rule)
2384  return;
2385 
2386  QString label;
2387  QStringList groups;
2388  QStringList::Iterator it;
2389  MSqlQuery query(MSqlQuery::InitCon());
2390 
2391  // Recording Profile
2392  if (m_recprofileList)
2393  {
2394  if (!m_loaded)
2395  {
2396  label = QObject::tr("Record using the %1 profile");
2397 
2399  label.arg(QObject::tr("Default")),
2400  qVariantFromValue(QString("Default")));
2401  // LiveTV profile - it's for LiveTV not scheduled recordings??
2403  label.arg(QObject::tr("LiveTV")),
2404  qVariantFromValue(QString("LiveTV")));
2406  label.arg(QObject::tr("High Quality")),
2407  qVariantFromValue(QString("High Quality")));
2409  label.arg(QObject::tr("Low Quality")),
2410  qVariantFromValue(QString("Low Quality")));
2411  }
2413  }
2414 
2415  // Recording Group
2416  if (m_recgroupList)
2417  {
2418  if (!m_loaded)
2419  {
2420  label = QObject::tr("Include in the \"%1\" recording group");
2422  QObject::tr("Create a new recording group"),
2423  qVariantFromValue(QString("__NEW_GROUP__")));
2424 
2425  query.prepare("SELECT recgroupid, recgroup FROM recgroups "
2426  "WHERE recgroup <> 'Deleted' AND "
2427  " recgroup <> 'LiveTV' "
2428  "ORDER BY special DESC, recgroup ASC"); // Special groups first
2429  if (query.exec())
2430  {
2431  while (query.next())
2432  {
2433  int id = query.value(0).toInt();
2434  QString name = query.value(1).toString();
2435 
2436  if (name == "Default")
2437  name = QObject::tr("Default");
2438  new MythUIButtonListItem(m_recgroupList, label.arg(name),
2439  qVariantFromValue(id));
2440  }
2441  }
2442 
2443  }
2445  }
2446 
2447  // Storage Group
2448  if (m_storagegroupList)
2449  {
2450  if (!m_loaded)
2451  {
2452  label = QObject::tr("Store in the \"%1\" storage group");
2454  label.arg(QObject::tr("Default")),
2455  qVariantFromValue(QString("Default")));
2456 
2458  for (it = groups.begin(); it != groups.end(); ++it)
2459  {
2460  if ((*it).compare("Default", Qt::CaseInsensitive) != 0)
2462  label.arg(*it), qVariantFromValue(*it));
2463  }
2464  }
2466  }
2467 
2468  // Playback Group
2469  if (m_playgroupList)
2470  {
2471  if (!m_loaded)
2472  {
2473  label = QObject::tr("Use \"%1\" playback group settings");
2475  label.arg(QObject::tr("Default")),
2476  qVariantFromValue(QString("Default")));
2477 
2478  groups = PlayGroup::GetNames();
2479  for (it = groups.begin(); it != groups.end(); ++it)
2480  {
2481  new MythUIButtonListItem(m_playgroupList, label.arg(*it),
2482  qVariantFromValue(*it));
2483  }
2484  }
2486  }
2487 
2488  // Max Episodes
2489  if (m_maxepSpin)
2490  {
2491  if (!m_loaded)
2492  {
2493  int maxEpisodes = m_rule->m_maxEpisodes;
2494  m_maxepSpin->SetRange(0,100,1,5);
2495  m_rule->m_maxEpisodes = maxEpisodes;
2496  }
2498  }
2499 
2500  // Max Episode Behaviour
2501  if (m_maxbehaviourList)
2502  {
2503  if (!m_loaded)
2504  {
2506  QObject::tr("Don't record if this would exceed the max "
2507  "episodes"), qVariantFromValue(false));
2509  QObject::tr("Delete oldest if this would exceed the max "
2510  "episodes"), qVariantFromValue(true));
2511  }
2513  }
2514 
2515  // Auto-Expire
2516  if (m_autoexpireCheck)
2517  {
2519  }
2520 
2521  m_loaded = true;
2522 
2523  RuleChanged();
2524 }
2525 
2527 {
2528  if (!m_rule)
2529  return;
2530 
2531  if (m_recprofileList)
2533 
2534  if (m_recgroupList)
2535  {
2536  // If the user selected 'Create a new regroup' but failed to enter a
2537  // name when prompted, restore the original value
2538  if (m_recgroupList->GetDataValue().toString() == "__NEW_GROUP__")
2541  }
2542 
2543  if (m_storagegroupList)
2545 
2546  if (m_playgroupList)
2548 
2549  if (m_maxepSpin)
2551 
2552  if (m_maxbehaviourList)
2554 
2555  if (m_autoexpireCheck)
2557 }
2558 
2560 {
2561  if (!m_rule)
2562  return;
2563 
2564  bool isScheduled = (m_rule->m_type != kNotRecording &&
2565  m_rule->m_type != kDontRecord);
2566  bool isSingle = (m_rule->m_type == kSingleRecord ||
2568 
2569  if (m_recprofileList)
2570  m_recprofileList->SetEnabled(isScheduled);
2571  if (m_recgroupList)
2572  m_recgroupList->SetEnabled(isScheduled);
2573  if (m_storagegroupList)
2574  m_storagegroupList->SetEnabled(isScheduled);
2575  if (m_playgroupList)
2576  m_playgroupList->SetEnabled(isScheduled);
2577  if (m_maxepSpin)
2578  m_maxepSpin->SetEnabled(isScheduled && !isSingle);
2579  if (m_maxbehaviourList)
2580  m_maxbehaviourList->SetEnabled(isScheduled && !isSingle &&
2581  m_rule->m_maxEpisodes != 0);
2582  if (m_autoexpireCheck)
2583  m_autoexpireCheck->SetEnabled(isScheduled);
2584 }
2585 
2587 {
2588  if (!item || !m_rule)
2589  return;
2590 
2591  m_rule->m_maxEpisodes = item->GetData().toInt();
2592 
2593  if (m_maxbehaviourList)
2595 }
2596 
2598 {
2599  if (!m_rule)
2600  return;
2601 
2602  if (m_recgroupList->GetDataValue().toString() != "__NEW_GROUP__")
2603  return;
2604 
2605  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2606 
2607  QString label =
2608  QObject::tr("New Recording group name: ");
2609 
2610  MythTextInputDialog *textDialog =
2611  new MythTextInputDialog(popupStack, label,
2612  static_cast<InputFilter>(FilterSymbols | FilterPunct));
2613 
2614  textDialog->SetReturnEvent(m_screen, "newrecgroup");
2615 
2616  if (textDialog->Create())
2617  popupStack->AddScreen(textDialog, false);
2618 }
2619 
2620 void StoreOptMixin::SetRecGroup(int recgroupID, QString recgroup)
2621 {
2622  if (!m_rule || recgroupID <= 0)
2623  return;
2624 
2625  if (m_recgroupList)
2626  {
2627  recgroup = recgroup.trimmed();
2628  if (recgroup.isEmpty())
2629  return;
2630 
2631  QString label = QObject::tr("Include in the \"%1\" recording group");
2632  MythUIButtonListItem *item =
2633  new MythUIButtonListItem(m_recgroupList, label.arg(recgroup),
2634  qVariantFromValue(recgroup));
2636 
2637  if (m_other && m_other->m_recgroupList)
2638  {
2640  label.arg(recgroup), qVariantFromValue(recgroupID));
2642  }
2643  }
2644 }
2645 
2646 int StoreOptMixin::CreateRecordingGroup(const QString& groupName)
2647 {
2648  int groupID = -1;
2649  MSqlQuery query(MSqlQuery::InitCon());
2650 
2651  query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
2652  "displayname = :DISPLAYNAME");
2653  query.bindValue(":NAME", groupName);
2654  query.bindValue(":DISPLAYNAME", groupName);
2655 
2656  if (query.exec())
2657  groupID = query.lastInsertId().toInt();
2658 
2659  if (groupID <= 0)
2660  LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
2661  "Does it already exist?").arg(groupName));
2662 
2663  return groupID;
2664 }
2665 
2667 
2674  PostProcMixin *other)
2675  : m_commflagCheck(nullptr), m_transcodeCheck(nullptr),
2676  m_transcodeprofileList(nullptr), m_userjob1Check(nullptr),
2677  m_userjob2Check(nullptr), m_userjob3Check(nullptr), m_userjob4Check(nullptr),
2678  m_metadataLookupCheck(nullptr),
2679  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2680 {
2681 }
2682 
2683 void PostProcMixin::Create(bool *err)
2684 {
2685  if (!m_rule)
2686  return;
2687 
2688  if (m_other && !m_other->m_commflagCheck)
2689  UIUtilE::Assign(m_screen, m_commflagCheck, "autocommflag", err);
2690  else
2691  UIUtilW::Assign(m_screen, m_commflagCheck, "autocommflag");
2692 
2693  if (m_other && !m_other->m_transcodeCheck)
2694  UIUtilE::Assign(m_screen, m_transcodeCheck, "autotranscode", err);
2695  else
2696  UIUtilW::Assign(m_screen, m_transcodeCheck, "autotranscode");
2697 
2699  UIUtilE::Assign(m_screen, m_transcodeprofileList, "transcodeprofile", err);
2700  else
2701  UIUtilW::Assign(m_screen, m_transcodeprofileList, "transcodeprofile");
2702 
2703  if (m_other && !m_other->m_userjob1Check)
2704  UIUtilE::Assign(m_screen, m_userjob1Check, "userjob1", err);
2705  else
2707 
2708  if (m_other && !m_other->m_userjob2Check)
2709  UIUtilE::Assign(m_screen, m_userjob2Check, "userjob2", err);
2710  else
2712 
2713  if (m_other && !m_other->m_userjob3Check)
2714  UIUtilE::Assign(m_screen, m_userjob3Check, "userjob3", err);
2715  else
2717 
2718  if (m_other && !m_other->m_userjob4Check)
2719  UIUtilE::Assign(m_screen, m_userjob4Check, "userjob4", err);
2720  else
2722 
2723  UIUtilW::Assign(m_screen, m_metadataLookupCheck, "metadatalookup");
2724 }
2725 
2727 {
2728  if (!m_rule)
2729  return;
2730 
2731  // Auto-commflag
2732  if (m_commflagCheck)
2733  {
2735  }
2736 
2737  // Auto-transcode
2738  if (m_transcodeCheck)
2739  {
2741  }
2742 
2743  // Transcode Method
2745  {
2746  if (!m_loaded)
2747  {
2748  QMap<int, QString> profiles = RecordingProfile::GetTranscodingProfiles();
2749  QMap<int, QString>::iterator it;
2750  for (it = profiles.begin(); it != profiles.end(); ++it)
2751  {
2753  qVariantFromValue(it.key()));
2754  }
2755  }
2757  }
2758 
2759  // User Job #1
2760  if (m_userjob1Check)
2761  {
2762  if (!m_loaded)
2763  {
2764  MythUIText *userjob1Text = nullptr;
2765  UIUtilW::Assign(m_screen, userjob1Text, "userjob1text");
2766  if (userjob1Text)
2767  userjob1Text->SetText(QObject::tr("Run '%1'")
2768  .arg(gCoreContext->GetSetting("UserJobDesc1", "User Job 1")));
2769  }
2771  }
2772 
2773  // User Job #2
2774  if (m_userjob2Check)
2775  {
2776  if (!m_loaded)
2777  {
2778  MythUIText *userjob2Text = nullptr;
2779  UIUtilW::Assign(m_screen, userjob2Text, "userjob2text");
2780  if (userjob2Text)
2781  userjob2Text->SetText(QObject::tr("Run '%1'")
2782  .arg(gCoreContext->GetSetting("UserJobDesc2", "User Job 2")));
2783  }
2785  }
2786 
2787  // User Job #3
2788  if (m_userjob3Check)
2789  {
2790  if (!m_loaded)
2791  {
2792  MythUIText *userjob3Text = nullptr;
2793  UIUtilW::Assign(m_screen, userjob3Text, "userjob3text");
2794  if (userjob3Text)
2795  userjob3Text->SetText(QObject::tr("Run '%1'")
2796  .arg(gCoreContext->GetSetting("UserJobDesc3", "User Job 3")));
2797  }
2799  }
2800 
2801  // User Job #4
2802  if (m_userjob4Check)
2803  {
2804  if (!m_loaded)
2805  {
2806  MythUIText *userjob4Text = nullptr;
2807  UIUtilW::Assign(m_screen, userjob4Text, "userjob4text");
2808  if (userjob4Text)
2809  userjob4Text->SetText(QObject::tr("Run '%1'")
2810  .arg(gCoreContext->GetSetting("UserJobDesc4", "User Job 4")));
2811  }
2813  }
2814 
2815  // Auto Metadata Lookup
2817  {
2819  }
2820 
2821  m_loaded = true;
2822 
2823  RuleChanged();
2824 }
2825 
2827 {
2828  if (!m_rule)
2829  return;
2830 
2831  if (m_commflagCheck)
2833  if (m_transcodeCheck)
2837  if (m_userjob1Check)
2839  if (m_userjob2Check)
2841  if (m_userjob3Check)
2843  if (m_userjob4Check)
2848 }
2849 
2851 {
2852  if (!m_rule)
2853  return;
2854 
2855  bool isScheduled = (m_rule->m_type != kNotRecording &&
2856  m_rule->m_type != kDontRecord);
2857 
2858  if (m_commflagCheck)
2859  m_commflagCheck->SetEnabled(isScheduled);
2860  if (m_transcodeCheck)
2861  m_transcodeCheck->SetEnabled(isScheduled);
2863  m_transcodeprofileList->SetEnabled(isScheduled &&
2865  if (m_userjob1Check)
2866  m_userjob1Check->SetEnabled(isScheduled);
2867  if (m_userjob2Check)
2868  m_userjob2Check->SetEnabled(isScheduled);
2869  if (m_userjob3Check)
2870  m_userjob3Check->SetEnabled(isScheduled);
2871  if (m_userjob4Check)
2872  m_userjob4Check->SetEnabled(isScheduled);
2874  m_metadataLookupCheck->SetEnabled(isScheduled);
2875 }
2876 
2878 {
2879  if (!m_rule)
2880  return;
2881 
2882  m_rule->m_autoTranscode = enable;
2883 
2886 }
QString m_subtitle
Definition: recordingrule.h:78
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:794
void Save(void) override
MythUICheckBox * m_commflagCheck
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)
Definition: mythdbcon.cpp:875
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)
MetadataLookupList results
void SetAutomatic(bool autom)
#define ENUM_TO_QVARIANT(a)
void UseTempTable(bool usetemp, QString table="record_tmp")
MythUISpinBox * m_endoffsetSpin
bool StartEmbedding(const QRect &)
Definition: tv_play.cpp:8684
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"))
StoreOptMixin(MythScreenType &screen, RecordingRule *rule, StoreOptMixin *other=nullptr)
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)
MetadataLookupList lookupList
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:154
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
Definition: recordingrule.h:96
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:168
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"))
RecordingInfo * m_recInfo
void CreateBusyDialog(QString title)
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void SetValue(int val) override
Definition: mythuispinbox.h:25
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 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
MetadataLookup * item
RecordingRule * m_recordingRule
MetadataLookup * CreateLookup(MetadataType mtype)
MythUICheckBox * m_metadataLookupCheck
int GetIntValue(void) const override
Definition: mythuispinbox.h:32
MythUIImage * m_fanart
uint GetSeason() const
void SetStep(LookupStep step)
RecordingDupMethodType
void SetNameFilter(QStringList filter)
QVariant value(int i) const
Definition: mythdbcon.h:182
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
void SetValueByData(QVariant data)
void Load(void) override
MythUICheckBox * m_transcodeCheck
This class is used as a container for messages.
Definition: mythevent.h:15
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:889
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)
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)
PostProcMixin(MythScreenType &screen, RecordingRule *rule, PostProcMixin *other=nullptr)
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:288
QString GetMasterHostName(void)
RecordingRule * m_rule
QVariant GetDataValue() const
MythUIButton * m_saveButton
FilterOptMixin(MythScreenType &screen, RecordingRule *rule, FilterOptMixin *other=nullptr)
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
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:360
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:547
void FindNetArt(VideoArtworkType type)
void Save(void) override
MythUIBusyDialog * m_busyPopup
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:31
void SetDownloads(ArtworkMap map)
void SetRecGroup(int recgroupID, QString recgroup)
QString GetInetref() const
bool Create(void) override
const char * name
Definition: ParseText.cpp:339
void ShowSchedOpt(void)
void ShowFilters(void)
FilterOptMixin * m_other
void ShowMetadataOptions(void)
QString m_seriesid
Definition: recordingrule.h:90
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:92
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:417
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:819
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:56
void OnSearchListSelection(RefCountHandler< MetadataLookup > lookup)
void QueryComplete(MetadataLookup *lookup)
QString m_title
Recording rule is enabled?
Definition: recordingrule.h:76
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 OnImageSearchListSelection(ArtworkInfo info, VideoArtworkType type)
void SetSubtype(LookupType subtype)
MythUIButtonList * m_maxbehaviourList
QString m_recProfile
uint GetRecordingRuleID(void) const
Definition: programinfo.h:443
void SetRule(RecordingRule *rule)
MetadataLookupList lookupList
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:83
MythUICheckBox * m_userjob1Check
void Load(void) override=0
void LoadTemplate(QString name)
void SetItemCurrent(MythUIButtonListItem *item)
bool LoadTemplate(QString category, QString categoryType="Default")
MythUIButton * m_queryButton
DownloadMap GetDownloads() const
void Load(void) override
MetadataImageDownload * m_imageDownload
MythUIButton * m_localCoverartButton
static QStringList GetTemplateNames(void)
void PromptForRecGroup(void)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:615
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...
ArtworkMap GetArtwork(QString inetref, uint season, bool strict)
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:367
void ShowPreviousView(void)
MythUIButtonList * m_recprofileList
CategoryType GetCategoryType(void) const
Definition: programinfo.h:432
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.
QString GetText(void) const
MythNotificationCenter * GetNotificationCenter(void)
MythUIButtonListItem * GetItemCurrent() const
bool Create(void) override
MythUIButtonList * m_rulesList
uint GetEpisode(void) const
Definition: programinfo.h:361
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:1251
void customEvent(QEvent *event) override
void HandleDownloadedImages(MetadataLookup *lookup)